上传ios工程资源包2
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// HJDanmakuView.h
|
||||
// HJDanmakuDemo
|
||||
//
|
||||
// Created by haijiao on 2017/7/6.
|
||||
// Copyright © 2017年 olinone. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "HJDanmakuConfiguration.h"
|
||||
#import "HJDanmakuModel.h"
|
||||
#import "HJDanmakuCell.h"
|
||||
|
||||
@class HJDanmakuView;
|
||||
@protocol HJDanmakuViewDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
|
||||
// preparate completed. you can start render after callback
|
||||
- (void)prepareCompletedWithDanmakuView:(HJDanmakuView *)danmakuView;
|
||||
|
||||
// called before render. return NO will ignore danmaku
|
||||
- (BOOL)danmakuView:(HJDanmakuView *)danmakuView shouldRenderDanmaku:(HJDanmakuModel *)danmaku;
|
||||
|
||||
// display customization
|
||||
- (void)danmakuView:(HJDanmakuView *)danmakuView willDisplayCell:(HJDanmakuCell *)cell danmaku:(HJDanmakuModel *)danmaku;
|
||||
- (void)danmakuView:(HJDanmakuView *)danmakuView didEndDisplayCell:(HJDanmakuCell *)cell danmaku:(HJDanmakuModel *)danmaku;
|
||||
|
||||
// selection customization
|
||||
- (BOOL)danmakuView:(HJDanmakuView *)danmakuView shouldSelectCell:(HJDanmakuCell *)cell danmaku:(HJDanmakuModel *)danmaku;
|
||||
- (void)danmakuView:(HJDanmakuView *)danmakuView didSelectCell:(HJDanmakuCell *)cell danmaku:(HJDanmakuModel *)danmaku;
|
||||
|
||||
@end
|
||||
|
||||
//_______________________________________________________________________________________________________________
|
||||
|
||||
@protocol HJDanmakuViewDateSource;
|
||||
@interface HJDanmakuView : UIView
|
||||
|
||||
@property (nonatomic, weak) id <HJDanmakuViewDateSource> dataSource;
|
||||
@property (nonatomic, weak) id <HJDanmakuViewDelegate> delegate;
|
||||
|
||||
@property (readonly) HJDanmakuConfiguration *configuration;
|
||||
@property (readonly) BOOL isPrepared;
|
||||
@property (readonly) BOOL isPlaying;
|
||||
|
||||
// traverse touches outside of the danmaku view, default NO
|
||||
@property (nonatomic, assign) BOOL traverseTouches;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame configuration:(HJDanmakuConfiguration *)configuration;
|
||||
|
||||
- (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier;
|
||||
- (__kindof HJDanmakuCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier;
|
||||
|
||||
- (__kindof HJDanmakuModel *)danmakuForVisibleCell:(HJDanmakuCell *)danmakuCell; // returns nil if cell is not visible
|
||||
@property (nonatomic, readonly) NSArray<__kindof HJDanmakuCell *> *visibleCells;
|
||||
|
||||
// you can prepare with nil when liveModel
|
||||
- (void)prepareDanmakus:(NSArray<HJDanmakuModel *> *)danmakus;
|
||||
|
||||
// be sure to call -prepareDanmakus before -play, when isPrepared is NO, call will be invalid
|
||||
- (void)play;
|
||||
- (void)pause;
|
||||
- (void)stop;
|
||||
|
||||
// reset and clear all danmakus, must call -prepareDanmakus before -play once again
|
||||
- (void)reset;
|
||||
- (void)clearScreen;
|
||||
|
||||
|
||||
/* send customization. when force, renderer will draw the danmaku immediately and ignore the maximum quantity limit.
|
||||
you should call -sendDanmakus: instead of -sendDanmaku:forceRender: to send the danmakus from a remote servers
|
||||
*/
|
||||
- (void)sendDanmaku:(HJDanmakuModel *)danmaku forceRender:(BOOL)force;
|
||||
- (void)sendDanmakus:(NSArray<HJDanmakuModel *> *)danmakus;
|
||||
|
||||
@end
|
||||
|
||||
//_______________________________________________________________________________________________________________
|
||||
|
||||
@protocol HJDanmakuViewDateSource <NSObject>
|
||||
|
||||
@required
|
||||
|
||||
// variable cell width support
|
||||
- (CGFloat)danmakuView:(HJDanmakuView *)danmakuView widthForDanmaku:(HJDanmakuModel *)danmaku;
|
||||
|
||||
// cell display. implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
|
||||
- (HJDanmakuCell *)danmakuView:(HJDanmakuView *)danmakuView cellForDanmaku:(HJDanmakuModel *)danmaku;
|
||||
|
||||
@optional
|
||||
|
||||
// current play time, unit second, must implementation when videoModel
|
||||
- (float)playTimeWithDanmakuView:(HJDanmakuView *)danmakuView;
|
||||
|
||||
// play buffer status, when YES, stop render new danmaku, rendered danmaku in screen will continue anim until disappears, only valid when videoModel
|
||||
- (BOOL)bufferingWithDanmakuView:(HJDanmakuView *)danmakuView;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// libcomMasonry.h
|
||||
// libcomMasonry
|
||||
//
|
||||
// Created by 4Ndf on 2019/4/15.
|
||||
// Copyright © 2019年 Dcloud. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
//! Project version number for libcomMasonry.
|
||||
FOUNDATION_EXPORT double libcomMasonryVersionNumber;
|
||||
|
||||
//! Project version string for libcomMasonry.
|
||||
FOUNDATION_EXPORT const unsigned char libcomMasonryVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <DCUniVideoPublic/PublicHeader.h>
|
||||
|
||||
|
||||
#import "MASUtilities.h"
|
||||
#import "View+MASAdditions.h"
|
||||
#import "View+MASShorthandAdditions.h"
|
||||
#import "ViewController+MASAdditions.h"
|
||||
#import "NSArray+MASAdditions.h"
|
||||
#import "NSArray+MASShorthandAdditions.h"
|
||||
#import "MASConstraint.h"
|
||||
#import "MASCompositeConstraint.h"
|
||||
#import "MASViewAttribute.h"
|
||||
#import "MASViewConstraint.h"
|
||||
#import "MASConstraintMaker.h"
|
||||
#import "MASLayoutConstraint.h"
|
||||
#import "NSLayoutConstraint+MASDebugAdditions.h"
|
||||
Binary file not shown.
@@ -0,0 +1,313 @@
|
||||
//
|
||||
// KSCrash.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-01-28.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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/Foundation.h>
|
||||
|
||||
#import "KSCrashReportWriter.h"
|
||||
#import "KSCrashReportFilter.h"
|
||||
#import "KSCrashMonitorType.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KSCrashDemangleLanguageNone = 0,
|
||||
KSCrashDemangleLanguageCPlusPlus = 1,
|
||||
KSCrashDemangleLanguageSwift = 2,
|
||||
KSCrashDemangleLanguageAll = ~1
|
||||
} KSCrashDemangleLanguage;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KSCDeleteNever,
|
||||
KSCDeleteOnSucess,
|
||||
KSCDeleteAlways
|
||||
} KSCDeleteBehavior;
|
||||
|
||||
/**
|
||||
* Reports any crashes that occur in the application.
|
||||
*
|
||||
* The crash reports will be located in $APP_HOME/Library/Caches/KSCrashReports
|
||||
*/
|
||||
@interface KSCrash : NSObject
|
||||
|
||||
#pragma mark - Configuration -
|
||||
|
||||
/** Init KSCrash instance with custom base path. */
|
||||
- (id) initWithBasePath:(NSString *)basePath;
|
||||
|
||||
/** A dictionary containing any info you'd like to appear in crash reports. Must
|
||||
* contain only JSON-safe data: NSString for keys, and NSDictionary, NSArray,
|
||||
* NSString, NSDate, and NSNumber for values.
|
||||
*
|
||||
* Default: nil
|
||||
*/
|
||||
@property(atomic,readwrite,retain) NSDictionary* userInfo;
|
||||
|
||||
/** What to do after sending reports via sendAllReportsWithCompletion:
|
||||
*
|
||||
* - Use KSCDeleteNever if you will manually manage the reports.
|
||||
* - Use KSCDeleteAlways if you will be using an alert confirmation (otherwise it
|
||||
* will nag the user incessantly until he selects "yes").
|
||||
* - Use KSCDeleteOnSuccess for all other situations.
|
||||
*
|
||||
* Default: KSCDeleteAlways
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) KSCDeleteBehavior deleteBehaviorAfterSendAll;
|
||||
|
||||
/** The monitors that will or have been installed.
|
||||
* Note: This value may change once KSCrash is installed if some monitors
|
||||
* fail to install.
|
||||
*
|
||||
* Default: KSCrashMonitorTypeProductionSafeMinimal
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) KSCrashMonitorType monitoring;
|
||||
|
||||
/** Maximum time to allow the main thread to run without returning.
|
||||
* If a task occupies the main thread for longer than this interval, the
|
||||
* watchdog will consider the queue deadlocked and shut down the app and write a
|
||||
* crash report.
|
||||
*
|
||||
* Note: You must have added KSCrashMonitorTypeMainThreadDeadlock to the monitoring
|
||||
* property in order for this to have any effect.
|
||||
*
|
||||
* Warning: Make SURE that nothing in your app that runs on the main thread takes
|
||||
* longer to complete than this value or it WILL get shut down! This includes
|
||||
* your app startup process, so you may need to push app initialization to
|
||||
* another thread, or perhaps set this to a higher value until your application
|
||||
* has been fully initialized.
|
||||
*
|
||||
* WARNING: This is still causing false positives in some cases. Use at own risk!
|
||||
*
|
||||
* 0 = Disabled.
|
||||
*
|
||||
* Default: 0
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) double deadlockWatchdogInterval;
|
||||
|
||||
/** If YES, attempt to fetch dispatch queue names for each running thread.
|
||||
*
|
||||
* WARNING: There is a chance that this will crash on a ksthread_getQueueName() call!
|
||||
*
|
||||
* Enable at your own risk.
|
||||
*
|
||||
* Default: NO
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) BOOL searchQueueNames;
|
||||
|
||||
/** If YES, introspect memory contents during a crash.
|
||||
* Any Objective-C objects or C strings near the stack pointer or referenced by
|
||||
* cpu registers or exceptions will be recorded in the crash report, along with
|
||||
* their contents.
|
||||
*
|
||||
* Default: YES
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) BOOL introspectMemory;
|
||||
|
||||
/** If YES, monitor all Objective-C/Swift deallocations and keep track of any
|
||||
* accesses after deallocation.
|
||||
*
|
||||
* Default: NO
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) BOOL catchZombies;
|
||||
|
||||
/** List of Objective-C classes that should never be introspected.
|
||||
* Whenever a class in this list is encountered, only the class name will be recorded.
|
||||
* This can be useful for information security concerns.
|
||||
*
|
||||
* Default: nil
|
||||
*/
|
||||
@property(nonatomic,readwrite,retain) NSArray* doNotIntrospectClasses;
|
||||
|
||||
/** The maximum number of reports allowed on disk before old ones get deleted.
|
||||
*
|
||||
* Default: 5
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) int maxReportCount;
|
||||
|
||||
/** The report sink where reports get sent.
|
||||
* This MUST be set or else the reporter will not send reports (although it will
|
||||
* still record them).
|
||||
*
|
||||
* Note: If you use an installation, it will automatically set this property.
|
||||
* Do not modify it in such a case.
|
||||
*/
|
||||
@property(nonatomic,readwrite,retain) id<KSCrashReportFilter> sink;
|
||||
|
||||
/** C Function to call during a crash report to give the callee an opportunity to
|
||||
* add to the report. NULL = ignore.
|
||||
*
|
||||
* WARNING: Only call async-safe functions from this function! DO NOT call
|
||||
* Objective-C methods!!!
|
||||
*
|
||||
* Note: If you use an installation, it will automatically set this property.
|
||||
* Do not modify it in such a case.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) KSReportWriteCallback onCrash;
|
||||
|
||||
/** Add a copy of KSCrash's console log messages to the crash report.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) BOOL addConsoleLogToReport;
|
||||
|
||||
/** Print the previous app run log to the console when installing KSCrash.
|
||||
* This is primarily for debugging purposes.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) BOOL printPreviousLog;
|
||||
|
||||
/** Which languages to demangle when getting stack traces (default KSCrashDemangleLanguageAll) */
|
||||
@property(nonatomic,readwrite,assign) KSCrashDemangleLanguage demangleLanguages;
|
||||
|
||||
/** Exposes the uncaughtExceptionHandler if set from KSCrash. Is nil if debugger is running. **/
|
||||
@property (nonatomic, assign) NSUncaughtExceptionHandler *uncaughtExceptionHandler;
|
||||
|
||||
/** Exposes the currentSnapshotUserReportedExceptionHandler if set from KSCrash. Is nil if debugger is running. **/
|
||||
@property (nonatomic, assign) NSUncaughtExceptionHandler *currentSnapshotUserReportedExceptionHandler;
|
||||
|
||||
#pragma mark - Information -
|
||||
|
||||
/** Total active time elapsed since the last crash. */
|
||||
@property(nonatomic,readonly,assign) NSTimeInterval activeDurationSinceLastCrash;
|
||||
|
||||
/** Total time backgrounded elapsed since the last crash. */
|
||||
@property(nonatomic,readonly,assign) NSTimeInterval backgroundDurationSinceLastCrash;
|
||||
|
||||
/** Number of app launches since the last crash. */
|
||||
@property(nonatomic,readonly,assign) int launchesSinceLastCrash;
|
||||
|
||||
/** Number of sessions (launch, resume from suspend) since last crash. */
|
||||
@property(nonatomic,readonly,assign) int sessionsSinceLastCrash;
|
||||
|
||||
/** Total active time elapsed since launch. */
|
||||
@property(nonatomic,readonly,assign) NSTimeInterval activeDurationSinceLaunch;
|
||||
|
||||
/** Total time backgrounded elapsed since launch. */
|
||||
@property(nonatomic,readonly,assign) NSTimeInterval backgroundDurationSinceLaunch;
|
||||
|
||||
/** Number of sessions (launch, resume from suspend) since app launch. */
|
||||
@property(nonatomic,readonly,assign) int sessionsSinceLaunch;
|
||||
|
||||
/** If true, the application crashed on the previous launch. */
|
||||
@property(nonatomic,readonly,assign) BOOL crashedLastLaunch;
|
||||
|
||||
/** The total number of unsent reports. Note: This is an expensive operation. */
|
||||
@property(nonatomic,readonly,assign) int reportCount;
|
||||
|
||||
/** Information about the operating system and environment */
|
||||
@property(nonatomic,readonly,strong) NSDictionary* systemInfo;
|
||||
|
||||
#pragma mark - API -
|
||||
|
||||
/** Get the singleton instance of the crash reporter.
|
||||
*/
|
||||
+ (KSCrash*) sharedInstance;
|
||||
|
||||
/** Install the crash reporter.
|
||||
* The reporter will record crashes, but will not send any crash reports unless
|
||||
* sink is set.
|
||||
*
|
||||
* @return YES if the reporter successfully installed.
|
||||
*/
|
||||
- (BOOL) install;
|
||||
|
||||
/** Send all outstanding crash reports to the current sink.
|
||||
* It will only attempt to send the most recent 5 reports. All others will be
|
||||
* deleted. Once the reports are successfully sent to the server, they may be
|
||||
* deleted locally, depending on the property "deleteAfterSendAll".
|
||||
*
|
||||
* Note: property "sink" MUST be set or else this method will call onCompletion
|
||||
* with an error.
|
||||
*
|
||||
* @param onCompletion Called when sending is complete (nil = ignore).
|
||||
*/
|
||||
- (void) sendAllReportsWithCompletion:(KSCrashReportFilterCompletion) onCompletion;
|
||||
|
||||
/** Get all unsent report IDs.
|
||||
*
|
||||
* @return An array with report IDs.
|
||||
*/
|
||||
- (NSArray*) reportIDs;
|
||||
|
||||
/** Get report.
|
||||
*
|
||||
* @param reportID An ID of report.
|
||||
*
|
||||
* @return A dictionary with report fields. See KSCrashReportFields.h for available fields.
|
||||
*/
|
||||
- (NSDictionary*) reportWithID:(NSNumber*) reportID;
|
||||
|
||||
/** Delete all unsent reports.
|
||||
*/
|
||||
- (void) deleteAllReports;
|
||||
|
||||
/** Delete report.
|
||||
*
|
||||
* @param reportID An ID of report to delete.
|
||||
*/
|
||||
- (void) deleteReportWithID:(NSNumber*) reportID;
|
||||
|
||||
/** Report a custom, user defined exception.
|
||||
* This can be useful when dealing with scripting languages.
|
||||
*
|
||||
* If terminateProgram is true, all sentries will be uninstalled and the application will
|
||||
* terminate with an abort().
|
||||
*
|
||||
* @param name The exception name (for namespacing exception types).
|
||||
*
|
||||
* @param reason A description of why the exception occurred.
|
||||
*
|
||||
* @param language A unique language identifier.
|
||||
*
|
||||
* @param lineOfCode A copy of the offending line of code (nil = ignore).
|
||||
*
|
||||
* @param stackTrace An array of frames (dictionaries or strings) representing the call stack leading to the exception (nil = ignore).
|
||||
*
|
||||
* @param logAllThreads If true, suspend all threads and log their state. Note that this incurs a
|
||||
* performance penalty, so it's best to use only on fatal errors.
|
||||
*
|
||||
* @param terminateProgram If true, do not return from this function call. Terminate the program instead.
|
||||
*/
|
||||
- (void) reportUserException:(NSString*) name
|
||||
reason:(NSString*) reason
|
||||
language:(NSString*) language
|
||||
lineOfCode:(NSString*) lineOfCode
|
||||
stackTrace:(NSArray*) stackTrace
|
||||
logAllThreads:(BOOL) logAllThreads
|
||||
terminateProgram:(BOOL) terminateProgram;
|
||||
|
||||
/** Experimental feature. Works like LD_PRELOAD. Enable C++ exceptions catching with __cxa_throw swap,
|
||||
* by updating pointers in the indirect symbol table, which is located in the __LINKEDIT segment.
|
||||
* It supports getting a true stackstace even in dynamically linked libraries.
|
||||
* Also allows a user to override original __cxa_throw with his implementation.
|
||||
*/
|
||||
- (void) enableSwapOfCxaThrow;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
//! Project version number for KSCrashFramework.
|
||||
FOUNDATION_EXPORT const double KSCrashFrameworkVersionNumber;
|
||||
|
||||
//! Project version string for KSCrashFramework.
|
||||
FOUNDATION_EXPORT const unsigned char KSCrashFrameworkVersionString[];
|
||||
@@ -0,0 +1,277 @@
|
||||
//
|
||||
// KSCrashC.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-01-28.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/* Primary C entry point into the crash reporting system.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_KSCrashC_h
|
||||
#define HDR_KSCrashC_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include "KSCrashMonitorType.h"
|
||||
#include "KSCrashReportWriter.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
/** Install the crash reporter. The reporter will record the next crash and then
|
||||
* terminate the program.
|
||||
*
|
||||
* @param installPath Directory to install to.
|
||||
*
|
||||
* @return The crash types that are being handled.
|
||||
*/
|
||||
KSCrashMonitorType kscrash_install(const char* appName, const char* const installPath);
|
||||
|
||||
/** Set the crash types that will be handled.
|
||||
* Some crash types may not be enabled depending on circumstances (e.g. running
|
||||
* in a debugger).
|
||||
*
|
||||
* @param monitors The monitors to install.
|
||||
*
|
||||
* @return The monitors that were installed. If KSCrash has been
|
||||
* installed, the return value represents the monitors that were
|
||||
* successfully installed. Otherwise it represents which monitors it
|
||||
* will attempt to activate when KSCrash installs.
|
||||
*/
|
||||
KSCrashMonitorType kscrash_setMonitoring(KSCrashMonitorType monitors);
|
||||
|
||||
/** Set the user-supplied data in JSON format.
|
||||
*
|
||||
* @param userInfoJSON Pre-baked JSON containing user-supplied information.
|
||||
* NULL = delete.
|
||||
*/
|
||||
void kscrash_setUserInfoJSON(const char* const userInfoJSON);
|
||||
|
||||
/** Set the maximum time to allow the main thread to run without returning.
|
||||
* If a task occupies the main thread for longer than this interval, the
|
||||
* watchdog will consider the queue deadlocked and shut down the app and write a
|
||||
* crash report.
|
||||
*
|
||||
* Warning: Make SURE that nothing in your app that runs on the main thread takes
|
||||
* longer to complete than this value or it WILL get shut down! This includes
|
||||
* your app startup process, so you may need to push app initialization to
|
||||
* another thread, or perhaps set this to a higher value until your application
|
||||
* has been fully initialized.
|
||||
*
|
||||
* 0 = Disabled.
|
||||
*
|
||||
* Default: 0
|
||||
*/
|
||||
void kscrash_setDeadlockWatchdogInterval(double deadlockWatchdogInterval);
|
||||
|
||||
/** If true, attempt to fetch dispatch queue names for each running thread.
|
||||
*
|
||||
* WARNING: There is a chance that this will crash on a ksthread_getQueueName() call!
|
||||
*
|
||||
* Enable at your own risk.
|
||||
*
|
||||
* Default: false
|
||||
*/
|
||||
void kscrash_setSearchQueueNames(bool searchQueueNames);
|
||||
|
||||
/** If true, introspect memory contents during a crash.
|
||||
* Any Objective-C objects or C strings near the stack pointer or referenced by
|
||||
* cpu registers or exceptions will be recorded in the crash report, along with
|
||||
* their contents.
|
||||
*
|
||||
* Default: false
|
||||
*/
|
||||
void kscrash_setIntrospectMemory(bool introspectMemory);
|
||||
|
||||
/** List of Objective-C classes that should never be introspected.
|
||||
* Whenever a class in this list is encountered, only the class name will be recorded.
|
||||
* This can be useful for information security concerns.
|
||||
*
|
||||
* Default: NULL
|
||||
*/
|
||||
void kscrash_setDoNotIntrospectClasses(const char** doNotIntrospectClasses, int length);
|
||||
|
||||
/** Set the callback to invoke upon a crash.
|
||||
*
|
||||
* WARNING: Only call async-safe functions from this function! DO NOT call
|
||||
* Objective-C methods!!!
|
||||
*
|
||||
* @param onCrashNotify Function to call during a crash report to give the
|
||||
* callee an opportunity to add to the report.
|
||||
* NULL = ignore.
|
||||
*
|
||||
* Default: NULL
|
||||
*/
|
||||
void kscrash_setCrashNotifyCallback(const KSReportWriteCallback onCrashNotify);
|
||||
|
||||
typedef void (*KSReportWrittenCallback)(int64_t reportID);
|
||||
|
||||
/** Set the callback to invoke upon finishing writing a crash report.
|
||||
*
|
||||
* WARNING: Only call async-safe functions from this function! DO NOT call
|
||||
* Objective-C methods!!!
|
||||
*
|
||||
* @param onReportWrittenNotify Function to call after writing a crash report to
|
||||
* give the callee an opportunity to react to the report.
|
||||
* NULL = ignore.
|
||||
*
|
||||
* Default: NULL
|
||||
*/
|
||||
void kscrash_setReportWrittenCallback(const KSReportWrittenCallback onReportWrittenNotify);
|
||||
|
||||
/** Set if KSLOG console messages should be appended to the report.
|
||||
*
|
||||
* @param shouldAddConsoleLogToReport If true, add the log to the report.
|
||||
*/
|
||||
void kscrash_setAddConsoleLogToReport(bool shouldAddConsoleLogToReport);
|
||||
|
||||
/** Set if KSCrash should print the previous log to the console on startup.
|
||||
* This is for debugging purposes.
|
||||
*/
|
||||
void kscrash_setPrintPreviousLog(bool shouldPrintPreviousLog);
|
||||
|
||||
/** Set the maximum number of reports allowed on disk before old ones get deleted.
|
||||
*
|
||||
* @param maxReportCount The maximum number of reports.
|
||||
*/
|
||||
void kscrash_setMaxReportCount(int maxReportCount);
|
||||
|
||||
/** Report a custom, user defined exception.
|
||||
* This can be useful when dealing with scripting languages.
|
||||
*
|
||||
* If terminateProgram is true, all sentries will be uninstalled and the application will
|
||||
* terminate with an abort().
|
||||
*
|
||||
* @param name The exception name (for namespacing exception types).
|
||||
*
|
||||
* @param reason A description of why the exception occurred.
|
||||
*
|
||||
* @param language A unique language identifier.
|
||||
*
|
||||
* @param lineOfCode A copy of the offending line of code (NULL = ignore).
|
||||
*
|
||||
* @param stackTrace JSON encoded array containing stack trace information (one frame per array entry).
|
||||
* The frame structure can be anything you want, including bare strings.
|
||||
*
|
||||
* @param logAllThreads If true, suspend all threads and log their state. Note that this incurs a
|
||||
* performance penalty, so it's best to use only on fatal errors.
|
||||
*
|
||||
* @param terminateProgram If true, do not return from this function call. Terminate the program instead.
|
||||
*/
|
||||
void kscrash_reportUserException(const char* name,
|
||||
const char* reason,
|
||||
const char* language,
|
||||
const char* lineOfCode,
|
||||
const char* stackTrace,
|
||||
bool logAllThreads,
|
||||
bool terminateProgram);
|
||||
|
||||
/** Experimental feature. Works like LD_PRELOAD. Enable C++ exceptions catching with __cxa_throw swap,
|
||||
* by updating pointers in the indirect symbol table, which is located in the __LINKEDIT segment.
|
||||
* It supports getting a true stackstace even in dynamically linked libraries.
|
||||
* Also allows a user to override original __cxa_throw with his implementation.
|
||||
*/
|
||||
void enableSwapCxaThrow(void);
|
||||
|
||||
#pragma mark -- Notifications --
|
||||
|
||||
/** Notify the crash reporter of KSCrash being added to Objective-C runtime system.
|
||||
*/
|
||||
void kscrash_notifyObjCLoad(void);
|
||||
|
||||
/** Notify the crash reporter of the application active state.
|
||||
*
|
||||
* @param isActive true if the application is active, otherwise false.
|
||||
*/
|
||||
void kscrash_notifyAppActive(bool isActive);
|
||||
|
||||
/** Notify the crash reporter of the application foreground/background state.
|
||||
*
|
||||
* @param isInForeground true if the application is in the foreground, false if
|
||||
* it is in the background.
|
||||
*/
|
||||
void kscrash_notifyAppInForeground(bool isInForeground);
|
||||
|
||||
/** Notify the crash reporter that the application is terminating.
|
||||
*/
|
||||
void kscrash_notifyAppTerminate(void);
|
||||
|
||||
/** Notify the crash reporter that the application has crashed.
|
||||
*/
|
||||
void kscrash_notifyAppCrash(void);
|
||||
|
||||
|
||||
#pragma mark -- Reporting --
|
||||
|
||||
/** Get the number of reports on disk.
|
||||
*/
|
||||
int kscrash_getReportCount(void);
|
||||
|
||||
/** Get a list of IDs for all reports on disk.
|
||||
*
|
||||
* @param reportIDs An array big enough to hold all report IDs.
|
||||
* @param count How many reports the array can hold.
|
||||
*
|
||||
* @return The number of report IDs that were placed in the array.
|
||||
*/
|
||||
int kscrash_getReportIDs(int64_t* reportIDs, int count);
|
||||
|
||||
/** Read a report.
|
||||
*
|
||||
* @param reportID The report's ID.
|
||||
*
|
||||
* @return The NULL terminated report, or NULL if not found.
|
||||
* MEMORY MANAGEMENT WARNING: User is responsible for calling free() on the returned value.
|
||||
*/
|
||||
char* kscrash_readReport(int64_t reportID);
|
||||
|
||||
/** Add a custom report to the store.
|
||||
*
|
||||
* @param report The report's contents (must be JSON encoded).
|
||||
* @param reportLength The length of the report in bytes.
|
||||
*
|
||||
* @return the new report's ID.
|
||||
*/
|
||||
int64_t kscrash_addUserReport(const char* report, int reportLength);
|
||||
|
||||
/** Delete all reports on disk.
|
||||
*/
|
||||
void kscrash_deleteAllReports(void);
|
||||
|
||||
/** Delete report.
|
||||
*
|
||||
* @param reportID An ID of report to delete.
|
||||
*/
|
||||
void kscrash_deleteReportWithID(int64_t reportID);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSCrashC_h
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// KSCrashFramework.h
|
||||
// KSCrash-iOS
|
||||
//
|
||||
// Created by Josh Holtz on 3/2/16.
|
||||
// Copyright © 2016 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KSCrashFramework_h
|
||||
#define KSCrashFramework_h
|
||||
|
||||
#import "KSCrash.h"
|
||||
|
||||
#import "KSCrashC.h"
|
||||
#import "KSCrashInstallation.h"
|
||||
#import "KSCrashInstallation+Alert.h"
|
||||
#import "KSCrashInstallation+Private.h"
|
||||
#import "KSCrashInstallationConsole.h"
|
||||
#import "KSCrashInstallationEmail.h"
|
||||
#import "KSCrashInstallationQuincyHockey.h"
|
||||
#import "KSCrashInstallationStandard.h"
|
||||
#import "KSCrashInstallationVictory.h"
|
||||
#import "KSCrashMonitorContext.h"
|
||||
#import "KSCrashMonitor_System.h"
|
||||
#import "KSCrashReportFilter.h"
|
||||
#import "KSCrashReportFilterAlert.h"
|
||||
#import "KSCrashReportFilterAppleFmt.h"
|
||||
#import "KSCrashReportFilterBasic.h"
|
||||
#import "KSCrashReportFilterGZip.h"
|
||||
#import "KSCrashReportFilterJSON.h"
|
||||
#import "KSCrashReportFilterSets.h"
|
||||
#import "KSCrashReportFilterStringify.h"
|
||||
#import "KSCrashReportSinkConsole.h"
|
||||
#import "KSCrashReportSinkEMail.h"
|
||||
#import "KSCrashReportSinkQuincyHockey.h"
|
||||
#import "KSCrashReportSinkStandard.h"
|
||||
#import "KSCrashReportSinkVictory.h"
|
||||
#import "KSCrashReportWriter.h"
|
||||
#import "KSJSONCodecObjC.h"
|
||||
#import "NSData+KSGZip.h"
|
||||
|
||||
#endif /* KSCrashFramework_h */
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// KSCrashInstallation+Alert.h
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashInstallation.h"
|
||||
|
||||
@interface KSCrashInstallation (Alert)
|
||||
|
||||
/** Show an alert before sending any reports. Reports will only be sent if the user
|
||||
* presses the "yes" button.
|
||||
*
|
||||
* @param title The alert title.
|
||||
* @param message The message to show the user.
|
||||
* @param yesAnswer The text to display in the "yes" box.
|
||||
* @param noAnswer The text to display in the "no" box.
|
||||
*/
|
||||
- (void) addConditionalAlertWithTitle:(NSString*) title
|
||||
message:(NSString*) message
|
||||
yesAnswer:(NSString*) yesAnswer
|
||||
noAnswer:(NSString*) noAnswer;
|
||||
|
||||
/** Show an alert before sending any reports. Reports will be unconditionally sent
|
||||
* when the alert is dismissed.
|
||||
*
|
||||
* @param title The alert title.
|
||||
* @param message The message to show the user.
|
||||
* @param dismissButtonText The text to display in the dismiss button.
|
||||
*/
|
||||
- (void) addUnconditionalAlertWithTitle:(NSString*) title
|
||||
message:(NSString*) message
|
||||
dismissButtonText:(NSString*) dismissButtonText;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// KSCrashReportFieldProperties.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2013-02-10.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashInstallation.h"
|
||||
|
||||
|
||||
/** Implement a property to be used as a "key". */
|
||||
#define IMPLEMENT_REPORT_KEY_PROPERTY(NAME, NAMEUPPER) \
|
||||
@synthesize NAME##Key = _##NAME##Key; \
|
||||
- (void) set##NAMEUPPER##Key:(NSString*) value \
|
||||
{ \
|
||||
_##NAME##Key; \
|
||||
_##NAME##Key = value; \
|
||||
[self reportFieldForProperty:@#NAME setKey:value]; \
|
||||
}
|
||||
|
||||
/** Implement a property to be used as a "value". */
|
||||
#define IMPLEMENT_REPORT_VALUE_PROPERTY(NAME, NAMEUPPER, TYPE) \
|
||||
@synthesize NAME = _##NAME; \
|
||||
- (void) set##NAMEUPPER:(TYPE) value \
|
||||
{ \
|
||||
_##NAME; \
|
||||
_##NAME = value; \
|
||||
[self reportFieldForProperty:@#NAME setValue:value]; \
|
||||
}
|
||||
|
||||
/** Implement a standard report property (with key and value properties) */
|
||||
#define IMPLEMENT_REPORT_PROPERTY(NAME, NAMEUPPER, TYPE) \
|
||||
IMPLEMENT_REPORT_VALUE_PROPERTY(NAME, NAMEUPPER, TYPE) \
|
||||
IMPLEMENT_REPORT_KEY_PROPERTY(NAME, NAMEUPPER)
|
||||
|
||||
|
||||
@interface KSCrashInstallation ()
|
||||
|
||||
/** Initializer.
|
||||
*
|
||||
* @param requiredProperties Properties that MUST be set when sending reports.
|
||||
*/
|
||||
- (id) initWithRequiredProperties:(NSArray*) requiredProperties;
|
||||
|
||||
/** Set the key to be used for the specified report property.
|
||||
*
|
||||
* @param propertyName The name of the property.
|
||||
* @param key The key to use.
|
||||
*/
|
||||
- (void) reportFieldForProperty:(NSString*) propertyName setKey:(id) key;
|
||||
|
||||
/** Set the value of the specified report property.
|
||||
*
|
||||
* @param propertyName The name of the property.
|
||||
* @param value The value to set.
|
||||
*/
|
||||
- (void) reportFieldForProperty:(NSString*) propertyName setValue:(id) value;
|
||||
|
||||
/** Create a new sink. Subclasses must implement this.
|
||||
*/
|
||||
- (id<KSCrashReportFilter>) sink;
|
||||
|
||||
/** Make an absolute key path if the specified path is not already absolute. */
|
||||
- (NSString*) makeKeyPath:(NSString*) keyPath;
|
||||
|
||||
/** Make an absolute key paths from the specified paths. */
|
||||
- (NSArray*) makeKeyPaths:(NSArray*) keyPaths;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// KSCrashInstallation.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2013-02-10.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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/Foundation.h>
|
||||
#import "KSCrashReportFilter.h"
|
||||
#import "KSCrashReportWriter.h"
|
||||
|
||||
|
||||
/**
|
||||
* Crash system installation which handles backend-specific details.
|
||||
*
|
||||
* Only one installation can be installed at a time.
|
||||
*
|
||||
* This is an abstract class.
|
||||
*/
|
||||
@interface KSCrashInstallation : NSObject
|
||||
|
||||
/** C Function to call during a crash report to give the callee an opportunity to
|
||||
* add to the report. NULL = ignore.
|
||||
*
|
||||
* WARNING: Only call async-safe functions from this function! DO NOT call
|
||||
* Objective-C methods!!!
|
||||
*/
|
||||
@property(atomic,readwrite,assign) KSReportWriteCallback onCrash;
|
||||
|
||||
/** Install this installation. Call this instead of -[KSCrash install] to install
|
||||
* with everything needed for your particular backend.
|
||||
*/
|
||||
- (void) install;
|
||||
|
||||
/** Convenience method to call -[KSCrash sendAllReportsWithCompletion:].
|
||||
* This method will set the KSCrash sink and then send all outstanding reports.
|
||||
*
|
||||
* Note: Pay special attention to KSCrash's "deleteBehaviorAfterSendAll" property.
|
||||
*
|
||||
* @param onCompletion Called when sending is complete (nil = ignore).
|
||||
*/
|
||||
- (void) sendAllReportsWithCompletion:(KSCrashReportFilterCompletion) onCompletion;
|
||||
|
||||
/** Add a filter that gets executed before all normal filters.
|
||||
* Prepended filters will be executed in the order in which they were added.
|
||||
*
|
||||
* @param filter the filter to prepend.
|
||||
*/
|
||||
- (void) addPreFilter:(id<KSCrashReportFilter>) filter;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// KSCrashInstallationConsole.h
|
||||
// KSCrash-iOS
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashInstallation.h"
|
||||
|
||||
/** Prints all reports to the console.
|
||||
* This class is intended for testing purposes.
|
||||
*/
|
||||
@interface KSCrashInstallationConsole : KSCrashInstallation
|
||||
|
||||
@property(nonatomic,readwrite) BOOL printAppleFormat;
|
||||
|
||||
+ (instancetype) sharedInstance;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// KSCrashInstallationEmail.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2013-03-02.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashInstallation.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KSCrashEmailReportStyleJSON,
|
||||
KSCrashEmailReportStyleApple,
|
||||
} KSCrashEmailReportStyle;
|
||||
|
||||
/**
|
||||
* Email installation.
|
||||
* Sends reports via email.
|
||||
*/
|
||||
@interface KSCrashInstallationEmail : KSCrashInstallation
|
||||
|
||||
/** List of email addresses to send to (mandatory) */
|
||||
@property(nonatomic,readwrite,retain) NSArray* recipients;
|
||||
|
||||
/** Email subject (mandatory).
|
||||
*
|
||||
* Default: "Crash Report (YourBundleID)"
|
||||
*/
|
||||
@property(nonatomic,readwrite,retain) NSString* subject;
|
||||
|
||||
/** Message to accompany the reports (optional).
|
||||
*
|
||||
* Default: nil
|
||||
*/
|
||||
@property(nonatomic,readwrite,retain) NSString* message;
|
||||
|
||||
/** How to name the attachments (mandatory)
|
||||
*
|
||||
* You may use "%d" to differentiate when multiple reports are sent at once.
|
||||
*
|
||||
* Note: With the default filter set, files are gzipped text.
|
||||
*
|
||||
* Default: "crash-report-YourBundleID-%d.txt.gz"
|
||||
*/
|
||||
@property(nonatomic,readwrite,retain) NSString* filenameFmt;
|
||||
|
||||
/** Which report style to use.
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) KSCrashEmailReportStyle reportStyle;
|
||||
|
||||
/** Use the specified report format.
|
||||
*
|
||||
* useDefaultFilenameFormat If true, also change the filename format to the default
|
||||
* suitable for the report format.
|
||||
*/
|
||||
- (void) setReportStyle:(KSCrashEmailReportStyle)reportStyle
|
||||
useDefaultFilenameFormat:(BOOL) useDefaultFilenameFormat;
|
||||
|
||||
+ (instancetype) sharedInstance;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,129 @@
|
||||
//
|
||||
// KSCrashInstallationQuincyHockey.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2013-02-10.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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/Foundation.h>
|
||||
#import "KSCrashInstallation.h"
|
||||
#import "KSCrashReportWriter.h"
|
||||
|
||||
|
||||
/**
|
||||
* Common properties to both Quincy and Hockey.
|
||||
*
|
||||
* Generally, you only need to modify the value properties, not the "key" properties.
|
||||
* Any property that is set to nil won't be written to the crash report.
|
||||
*
|
||||
*
|
||||
* Key properties:
|
||||
*
|
||||
* The "key" properties specify what name the field will be stored under when
|
||||
* writing a crash report, and the value properties are the values that will
|
||||
* be written to the next crash report. The "key" properties are preset with
|
||||
* sensible defaults that you probably don't need to change.
|
||||
*
|
||||
* Using keypaths in key properties:
|
||||
*
|
||||
* Normally, "key" properties are meant to be retrieved from the "user" object at
|
||||
* the top level of the report. If you wish to retrieve the property from a different
|
||||
* part of the report, you can use keypath semantics. For example, "some_object/user_id"
|
||||
* will cause it to look in the "user" object of the report for "some_object", and then
|
||||
* inside that for "user_id".
|
||||
*
|
||||
* Using absolute keypaths will cause it to search from the report root. For
|
||||
* example, "/system/system_name" will look in the "system" object of the report for
|
||||
* "system_name".
|
||||
*
|
||||
* Note: The installation is incapable of storing directly to a keypath, so for
|
||||
* any property that uses keypaths, you must manually store the value to
|
||||
* the report using the custom onCrash callback.
|
||||
*
|
||||
* This is an abstract class.
|
||||
*/
|
||||
@interface KSCrashInstallationBaseQuincyHockey : KSCrashInstallation
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - Basic properties (nil by default) -
|
||||
// ======================================================================
|
||||
|
||||
// The values of these properties will be written to the next crash report.
|
||||
|
||||
@property(nonatomic,readwrite,retain) NSString* userID;
|
||||
@property(nonatomic,readwrite,retain) NSString* userName;
|
||||
@property(nonatomic,readwrite,retain) NSString* contactEmail;
|
||||
@property(nonatomic,readwrite,retain) NSString* crashDescription;
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - Advanced settings (normally you don't need to change these) -
|
||||
// ======================================================================
|
||||
|
||||
// The above properties will be written to the user section report using the
|
||||
// following keys.
|
||||
|
||||
@property(nonatomic,readwrite,retain) NSString* userIDKey;
|
||||
@property(nonatomic,readwrite,retain) NSString* userNameKey;
|
||||
@property(nonatomic,readwrite,retain) NSString* contactEmailKey;
|
||||
@property(nonatomic,readwrite,retain) NSString* crashDescriptionKey;
|
||||
|
||||
/** Data stored under these keys will be appended to the description
|
||||
* (in JSON format) before sending to Quincy/Hockey.
|
||||
*/
|
||||
@property(nonatomic,readwrite,retain) NSArray* extraDescriptionKeys;
|
||||
|
||||
/** If YES, wait until the host becomes reachable before trying to send.
|
||||
* If NO, it will attempt to send right away, and either succeed or fail.
|
||||
*
|
||||
* Default: YES
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) BOOL waitUntilReachable;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
* Quincy installation.
|
||||
*/
|
||||
@interface KSCrashInstallationQuincy : KSCrashInstallationBaseQuincyHockey
|
||||
|
||||
/** URL to send reports to (mandatory) */
|
||||
@property(nonatomic, readwrite, retain) NSURL* url;
|
||||
|
||||
+ (KSCrashInstallationQuincy*) sharedInstance;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
* Hockey installation.
|
||||
*/
|
||||
@interface KSCrashInstallationHockey: KSCrashInstallationBaseQuincyHockey
|
||||
|
||||
/** App identifier you received from Hockey (mandatory) */
|
||||
@property(nonatomic, readwrite, retain) NSString* appIdentifier;
|
||||
|
||||
+ (instancetype) sharedInstance;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// KSCrashInstallationStandard.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2013-03-02.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashInstallation.h"
|
||||
|
||||
|
||||
@interface KSCrashInstallationStandard : KSCrashInstallation
|
||||
|
||||
/** The URL to connect to. */
|
||||
@property(nonatomic,readwrite,retain) NSURL* url;
|
||||
|
||||
+ (instancetype) sharedInstance;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// KSCrashInstallationVictory.h
|
||||
//
|
||||
// Created by Kelp on 2013-03-14.
|
||||
//
|
||||
// Copyright (c) 2013 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashInstallation.h"
|
||||
|
||||
|
||||
/**
|
||||
Victory is an error reporting server in Python. It runs on Google App Engine.
|
||||
https://github.com/kelp404/Victory
|
||||
|
||||
You could download this project and then deploy to GAE with free plan.
|
||||
Your app could send error information to Victory with RESTful API.
|
||||
This is a demo site: https://victory-demo.appspot.com/
|
||||
*/
|
||||
@interface KSCrashInstallationVictory : KSCrashInstallation
|
||||
|
||||
/** The URL to connect to. */
|
||||
@property(nonatomic,readwrite,retain) NSURL* url;
|
||||
/** The user name of crash information *required. If value is nil it will be replaced with UIDevice.currentDevice.name */
|
||||
@property(nonatomic,readwrite,retain) NSString* userName;
|
||||
/** The user email of crash information *optional */
|
||||
@property(nonatomic,readwrite,retain) NSString* userEmail;
|
||||
|
||||
+ (instancetype) sharedInstance;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,240 @@
|
||||
//
|
||||
// KSCrashMonitorContext.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-12.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
#ifndef HDR_KSCrashMonitorContext_h
|
||||
#define HDR_KSCrashMonitorContext_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "KSCrashMonitorType.h"
|
||||
#include "KSMachineContext.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct KSCrash_MonitorContext
|
||||
{
|
||||
/** Unique identifier for this event. */
|
||||
const char* eventID;
|
||||
/**
|
||||
If true, so reported user exception will have the current snapshot.
|
||||
*/
|
||||
bool currentSnapshotUserReported;
|
||||
|
||||
/** If true, the environment has crashed hard, and only async-safe
|
||||
* functions should be used.
|
||||
*/
|
||||
bool requiresAsyncSafety;
|
||||
|
||||
/** If true, the crash handling system is currently handling a crash.
|
||||
* When false, all values below this field are considered invalid.
|
||||
*/
|
||||
bool handlingCrash;
|
||||
|
||||
/** If true, a second crash occurred while handling a crash. */
|
||||
bool crashedDuringCrashHandling;
|
||||
|
||||
/** If true, the registers contain valid information about the crash. */
|
||||
bool registersAreValid;
|
||||
|
||||
/** True if the crash system has detected a stack overflow. */
|
||||
bool isStackOverflow;
|
||||
|
||||
/** The machine context that generated the event. */
|
||||
struct KSMachineContext* offendingMachineContext;
|
||||
|
||||
/** Address that caused the fault. */
|
||||
uintptr_t faultAddress;
|
||||
|
||||
/** The type of crash that occurred.
|
||||
* This determines which other fields are valid. */
|
||||
KSCrashMonitorType crashType;
|
||||
|
||||
/** The name of the exception that caused the crash, if any. */
|
||||
const char* exceptionName;
|
||||
|
||||
/** Short description of why the crash occurred. */
|
||||
const char* crashReason;
|
||||
|
||||
/** The stack cursor for the trace leading up to the crash.
|
||||
* Note: Actual type is KSStackCursor*
|
||||
*/
|
||||
void* stackCursor;
|
||||
|
||||
struct
|
||||
{
|
||||
/** The mach exception type. */
|
||||
int type;
|
||||
|
||||
/** The mach exception code. */
|
||||
int64_t code;
|
||||
|
||||
/** The mach exception subcode. */
|
||||
int64_t subcode;
|
||||
} mach;
|
||||
|
||||
struct
|
||||
{
|
||||
/** The exception name. */
|
||||
const char* name;
|
||||
|
||||
/** The exception userInfo. */
|
||||
const char* userInfo;
|
||||
} NSException;
|
||||
|
||||
struct
|
||||
{
|
||||
/** The exception name. */
|
||||
const char* name;
|
||||
|
||||
} CPPException;
|
||||
|
||||
struct
|
||||
{
|
||||
/** User context information. */
|
||||
const void* userContext;
|
||||
int signum;
|
||||
int sigcode;
|
||||
} signal;
|
||||
|
||||
struct
|
||||
{
|
||||
/** The exception name. */
|
||||
const char* name;
|
||||
|
||||
/** The language the exception occured in. */
|
||||
const char* language;
|
||||
|
||||
/** The line of code where the exception occurred. Can be NULL. */
|
||||
const char* lineOfCode;
|
||||
|
||||
/** The user-supplied JSON encoded stack trace. */
|
||||
const char* customStackTrace;
|
||||
} userException;
|
||||
|
||||
struct
|
||||
{
|
||||
/** Total active time elapsed since the last crash. */
|
||||
double activeDurationSinceLastCrash;
|
||||
|
||||
/** Total time backgrounded elapsed since the last crash. */
|
||||
double backgroundDurationSinceLastCrash;
|
||||
|
||||
/** Number of app launches since the last crash. */
|
||||
int launchesSinceLastCrash;
|
||||
|
||||
/** Number of sessions (launch, resume from suspend) since last crash. */
|
||||
int sessionsSinceLastCrash;
|
||||
|
||||
/** Total active time elapsed since launch. */
|
||||
double activeDurationSinceLaunch;
|
||||
|
||||
/** Total time backgrounded elapsed since launch. */
|
||||
double backgroundDurationSinceLaunch;
|
||||
|
||||
/** Number of sessions (launch, resume from suspend) since app launch. */
|
||||
int sessionsSinceLaunch;
|
||||
|
||||
/** If true, the application crashed on the previous launch. */
|
||||
bool crashedLastLaunch;
|
||||
|
||||
/** If true, the application crashed on this launch. */
|
||||
bool crashedThisLaunch;
|
||||
|
||||
/** Timestamp for when the app state was last changed (active<->inactive,
|
||||
* background<->foreground) */
|
||||
double appStateTransitionTime;
|
||||
|
||||
/** If true, the application is currently active. */
|
||||
bool applicationIsActive;
|
||||
|
||||
/** If true, the application is currently in the foreground. */
|
||||
bool applicationIsInForeground;
|
||||
|
||||
} AppState;
|
||||
|
||||
/* Misc system information */
|
||||
struct
|
||||
{
|
||||
const char* systemName;
|
||||
const char* systemVersion;
|
||||
const char* machine;
|
||||
const char* model;
|
||||
const char* kernelVersion;
|
||||
const char* osVersion;
|
||||
bool isJailbroken;
|
||||
const char* bootTime;
|
||||
const char* appStartTime;
|
||||
const char* executablePath;
|
||||
const char* executableName;
|
||||
const char* bundleID;
|
||||
const char* bundleName;
|
||||
const char* bundleVersion;
|
||||
const char* bundleShortVersion;
|
||||
const char* appID;
|
||||
const char* cpuArchitecture;
|
||||
int cpuType;
|
||||
int cpuSubType;
|
||||
int binaryCPUType;
|
||||
int binaryCPUSubType;
|
||||
const char* timezone;
|
||||
const char* processName;
|
||||
int processID;
|
||||
int parentProcessID;
|
||||
const char* deviceAppHash;
|
||||
const char* buildType;
|
||||
uint64_t storageSize;
|
||||
uint64_t memorySize;
|
||||
uint64_t freeMemory;
|
||||
uint64_t usableMemory;
|
||||
} System;
|
||||
|
||||
struct
|
||||
{
|
||||
/** Address of the last deallocated exception. */
|
||||
uintptr_t address;
|
||||
|
||||
/** Name of the last deallocated exception. */
|
||||
const char* name;
|
||||
|
||||
/** Reason field from the last deallocated exception. */
|
||||
const char* reason;
|
||||
} ZombieException;
|
||||
|
||||
/** Full path to the console log, if any. */
|
||||
const char* consoleLogPath;
|
||||
|
||||
} KSCrash_MonitorContext;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSCrashMonitorContext_h
|
||||
@@ -0,0 +1,143 @@
|
||||
//
|
||||
// KSCrashMonitorType.h
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
#ifndef HDR_KSCrashMonitorType_h
|
||||
#define HDR_KSCrashMonitorType_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** Various aspects of the system that can be monitored:
|
||||
* - Mach kernel exception
|
||||
* - Fatal signal
|
||||
* - Uncaught C++ exception
|
||||
* - Uncaught Objective-C NSException
|
||||
* - Deadlock on the main thread
|
||||
* - User reported custom exception
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/* Captures and reports Mach exceptions. */
|
||||
KSCrashMonitorTypeMachException = 0x01,
|
||||
|
||||
/* Captures and reports POSIX signals. */
|
||||
KSCrashMonitorTypeSignal = 0x02,
|
||||
|
||||
/* Captures and reports C++ exceptions.
|
||||
* Note: This will slightly slow down exception processing.
|
||||
*/
|
||||
KSCrashMonitorTypeCPPException = 0x04,
|
||||
|
||||
/* Captures and reports NSExceptions. */
|
||||
KSCrashMonitorTypeNSException = 0x08,
|
||||
|
||||
/* Detects and reports a deadlock in the main thread. */
|
||||
KSCrashMonitorTypeMainThreadDeadlock = 0x10,
|
||||
|
||||
/* Accepts and reports user-generated exceptions. */
|
||||
KSCrashMonitorTypeUserReported = 0x20,
|
||||
|
||||
/* Keeps track of and injects system information. */
|
||||
KSCrashMonitorTypeSystem = 0x40,
|
||||
|
||||
/* Keeps track of and injects application state. */
|
||||
KSCrashMonitorTypeApplicationState = 0x80,
|
||||
|
||||
/* Keeps track of zombies, and injects the last zombie NSException. */
|
||||
KSCrashMonitorTypeZombie = 0x100,
|
||||
} KSCrashMonitorType;
|
||||
|
||||
#define KSCrashMonitorTypeAll \
|
||||
( \
|
||||
KSCrashMonitorTypeMachException | \
|
||||
KSCrashMonitorTypeSignal | \
|
||||
KSCrashMonitorTypeCPPException | \
|
||||
KSCrashMonitorTypeNSException | \
|
||||
KSCrashMonitorTypeMainThreadDeadlock | \
|
||||
KSCrashMonitorTypeUserReported | \
|
||||
KSCrashMonitorTypeSystem | \
|
||||
KSCrashMonitorTypeApplicationState | \
|
||||
KSCrashMonitorTypeZombie \
|
||||
)
|
||||
|
||||
#define KSCrashMonitorTypeExperimental \
|
||||
( \
|
||||
KSCrashMonitorTypeMainThreadDeadlock \
|
||||
)
|
||||
|
||||
#define KSCrashMonitorTypeDebuggerUnsafe \
|
||||
( \
|
||||
KSCrashMonitorTypeMachException | \
|
||||
KSCrashMonitorTypeSignal | \
|
||||
KSCrashMonitorTypeCPPException | \
|
||||
KSCrashMonitorTypeNSException \
|
||||
)
|
||||
|
||||
#define KSCrashMonitorTypeAsyncSafe \
|
||||
( \
|
||||
KSCrashMonitorTypeMachException | \
|
||||
KSCrashMonitorTypeSignal \
|
||||
)
|
||||
|
||||
#define KSCrashMonitorTypeOptional \
|
||||
( \
|
||||
KSCrashMonitorTypeZombie \
|
||||
)
|
||||
|
||||
#define KSCrashMonitorTypeAsyncUnsafe (KSCrashMonitorTypeAll & (~KSCrashMonitorTypeAsyncSafe))
|
||||
|
||||
/** Monitors that are safe to enable in a debugger. */
|
||||
#define KSCrashMonitorTypeDebuggerSafe (KSCrashMonitorTypeAll & (~KSCrashMonitorTypeDebuggerUnsafe))
|
||||
|
||||
/** Monitors that are safe to use in a production environment.
|
||||
* All other monitors should be considered experimental.
|
||||
*/
|
||||
#define KSCrashMonitorTypeProductionSafe (KSCrashMonitorTypeAll & (~KSCrashMonitorTypeExperimental))
|
||||
|
||||
/** Production safe monitors, minus the optional ones. */
|
||||
#define KSCrashMonitorTypeProductionSafeMinimal (KSCrashMonitorTypeProductionSafe & (~KSCrashMonitorTypeOptional))
|
||||
|
||||
/** Monitors that are required for proper operation.
|
||||
* These add essential information to the reports, but do not trigger reporting.
|
||||
*/
|
||||
#define KSCrashMonitorTypeRequired (KSCrashMonitorTypeSystem | KSCrashMonitorTypeApplicationState)
|
||||
|
||||
/** Effectively disables automatica reporting. The only way to generate a report
|
||||
* in this mode is by manually calling kscrash_reportUserException().
|
||||
*/
|
||||
#define KSCrashMonitorTypeManual (KSCrashMonitorTypeRequired | KSCrashMonitorTypeUserReported)
|
||||
|
||||
#define KSCrashMonitorTypeNone 0
|
||||
|
||||
const char* kscrashmonitortype_name(KSCrashMonitorType monitorType);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSCrashMonitorType_h
|
||||
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// KSCrashReportFilter.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-18.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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/Foundation.h>
|
||||
|
||||
/** Callback for filter operations.
|
||||
*
|
||||
* @param filteredReports The filtered reports (may be incomplete if "completed"
|
||||
* is false).
|
||||
* @param completed True if filtering completed.
|
||||
* Can be false due to a non-erroneous condition (such as a
|
||||
* user cancelling the operation).
|
||||
* @param error Non-nil if an error occurred.
|
||||
*/
|
||||
typedef void(^KSCrashReportFilterCompletion)(NSArray* filteredReports, BOOL completed, NSError* error);
|
||||
|
||||
|
||||
/**
|
||||
* A filter receives a set of reports, possibly transforms them, and then
|
||||
* calls a completion method.
|
||||
*/
|
||||
@protocol KSCrashReportFilter <NSObject>
|
||||
|
||||
/** Filter the specified reports.
|
||||
*
|
||||
* @param reports The reports to process.
|
||||
* @param onCompletion Block to call when processing is complete.
|
||||
*/
|
||||
- (void) filterReports:(NSArray*) reports
|
||||
onCompletion:(KSCrashReportFilterCompletion) onCompletion;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/** Conditionally call a completion method if it's not nil.
|
||||
*
|
||||
* @param onCompletion The completion block. If nil, this function does nothing.
|
||||
* @param filteredReports The parameter to send as "filteredReports".
|
||||
* @param completed The parameter to send as "completed".
|
||||
* @param error The parameter to send as "error".
|
||||
*/
|
||||
static inline void kscrash_callCompletion(KSCrashReportFilterCompletion onCompletion,
|
||||
NSArray* filteredReports,
|
||||
BOOL completed,
|
||||
NSError* error)
|
||||
{
|
||||
if(onCompletion)
|
||||
{
|
||||
onCompletion(filteredReports, completed, error);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// KSCrashReportFilterAlert.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-08-24.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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/Foundation.h>
|
||||
#import "KSCrashReportFilter.h"
|
||||
|
||||
|
||||
/** Pops up a standard alert window and awaits a user response before continuing.
|
||||
*
|
||||
* This filter can be set up as a conditional or unconditional filter. If both a
|
||||
* "yes" and "no" button are defined, it will only continue if the user presses
|
||||
* the "yes" button. If only a "yes" button is defined ("no" button is nil), it
|
||||
* will continue unconditionally when the alert is dismissed.
|
||||
*
|
||||
* Input: Any
|
||||
* Output: Same as input (passthrough)
|
||||
*/
|
||||
@interface KSCrashReportFilterAlert : NSObject <KSCrashReportFilter>
|
||||
|
||||
/**
|
||||
* @param title The title of the alert.
|
||||
* @param message The contents of the alert.
|
||||
* @param yesAnswer The text to put in the "yes" button.
|
||||
* @param noAnswer The text to put in the "no" button. If nil, the filter will
|
||||
* proceed unconditionally.
|
||||
*/
|
||||
+ (KSCrashReportFilterAlert*) filterWithTitle:(NSString*) title
|
||||
message:(NSString*) message
|
||||
yesAnswer:(NSString*) yesAnswer
|
||||
noAnswer:(NSString*) noAnswer;
|
||||
|
||||
/**
|
||||
* @param title The title of the alert.
|
||||
* @param message The contents of the alert.
|
||||
* @param yesAnswer The text to put in the "yes" button.
|
||||
* @param noAnswer The text to put in the "no" button. If nil, the filter will
|
||||
* proceed unconditionally.
|
||||
*/
|
||||
- (id) initWithTitle:(NSString*) title
|
||||
message:(NSString*) message
|
||||
yesAnswer:(NSString*) yesAnswer
|
||||
noAnswer:(NSString*) noAnswer;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,115 @@
|
||||
//
|
||||
// KSCrashReportFilterAppleFmt.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-24.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashReportFilter.h"
|
||||
|
||||
|
||||
/** Affects how an Apple-style crash report is generated.
|
||||
*
|
||||
* KSCrashReporter reports contain symbolication data which can be used in place
|
||||
* of normal offsets when generating an Apple-style report. The report style you
|
||||
* should choose depends on what symbols will be present in the application,
|
||||
* and what information will be available for offline symbolication (e.g. with
|
||||
* Apple's symbolication tools).
|
||||
*
|
||||
* There are three levels of symbolication:
|
||||
*
|
||||
* - Unsymbolicated: Contains a base address and an offset.
|
||||
* e.g. 0x0000347a 0x1000 + 9338
|
||||
*
|
||||
* - Basic: Contains base address, method name, and an offset into the method.
|
||||
* e.g. 0x372bd97e -[UIControl sendAction:to:forEvent:] + 38
|
||||
*
|
||||
* - Full: Similar to basic, but the offset is converted to a line number.
|
||||
* e.g. 0x0000347a +[MyObject someMethod] (MyObject.m:21)
|
||||
*
|
||||
* Full symbolication can only be done (and is only useful) for your own code.
|
||||
* Full symbolication information is only available from the dSYM file that
|
||||
* matches your app, so it can only be retrieved by offline symbolication.
|
||||
* For dynamic libraries (such as libc, UIKit, Foundation, etc), only basic
|
||||
* symbolication is available (online or offline).
|
||||
*
|
||||
* All iOS devices have basic symbol information on-board for dynamic libraries
|
||||
* (such as libc, UIKit, Foundation, etc). It's recommended to symbolicate these
|
||||
* on the device as it's not guaranteed that the machine you're offline
|
||||
* symbolicating from will have the same version available (for example, having
|
||||
* symbols available for iOS 4.2 - 5.01, but not for iOS 4.0).
|
||||
*
|
||||
* App symbols are present only if you have set "Strip Style" in your build
|
||||
* settings to "Debugging Symbols" (which strips all debugging symbols, but
|
||||
* leaves basic symbol information intact). This increases your app's code
|
||||
* footprint by about 10%, but allows basic symbolication on the device.
|
||||
*
|
||||
* Choosing KSAppleReportStylePartiallySymbolicated symbolicates everything
|
||||
* except main executable entries so that you can use an offline symbolicator.
|
||||
* You will need a dsym file to symbolicate those entries.
|
||||
*
|
||||
* KSAppleReportStyleSymbolicatedSideBySide generates a best-of-both-worlds
|
||||
* report where everything is symbolicated, but any offsets in the main
|
||||
* executable will retain both their "unsymbolicated" and "symbolicated"
|
||||
* versions side-by-side so that an offline symbolicator can still parse the
|
||||
* line and determine the line numbers (provided you have a matching dsym file).
|
||||
*
|
||||
* In short, if you're not worried about line numbers, or you don't want to
|
||||
* do offline symbolication, go with KSAppleReportStyleSymbolicated.
|
||||
* If you DO care about line numbers, have the dsym file handy, and will be
|
||||
* symbolicating offline, use KSAppleReportStyleSymbolicatedSideBySide.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** Leave all stack trace entries unsymbolicated. */
|
||||
KSAppleReportStyleUnsymbolicated,
|
||||
|
||||
/** Symbolicate all stack trace entries except for those in the main
|
||||
* executable.
|
||||
*/
|
||||
KSAppleReportStylePartiallySymbolicated,
|
||||
|
||||
/** Symbolicate all stack trace entries, but for any in the main executable,
|
||||
* put both an unsymbolicated and a symbolicated entry side-by-side.
|
||||
*/
|
||||
KSAppleReportStyleSymbolicatedSideBySide,
|
||||
|
||||
/** Symbolicate everything. */
|
||||
KSAppleReportStyleSymbolicated,
|
||||
} KSAppleReportStyle;
|
||||
|
||||
|
||||
/** Converts to Apple format.
|
||||
*
|
||||
* Input: NSDictionary
|
||||
* Output: NSString
|
||||
*/
|
||||
@interface KSCrashReportFilterAppleFmt : NSObject <KSCrashReportFilter>
|
||||
|
||||
+ (KSCrashReportFilterAppleFmt*) filterWithReportStyle:(KSAppleReportStyle) reportStyle;
|
||||
|
||||
- (id) initWithReportStyle:(KSAppleReportStyle) reportStyle;
|
||||
|
||||
- (NSString*)headerStringForSystemInfo:(NSDictionary*)system reportID:(NSString*)reportID crashTime:(NSDate*)crashTime;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,203 @@
|
||||
//
|
||||
// KSCrashReportFilterBasic.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-05-11.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashReportFilter.h"
|
||||
|
||||
|
||||
/**
|
||||
* Very basic filter that passes through reports untouched.
|
||||
*
|
||||
* Input: Anything.
|
||||
* Output: Same as input (passthrough).
|
||||
*/
|
||||
@interface KSCrashReportFilterPassthrough : NSObject <KSCrashReportFilter>
|
||||
|
||||
+ (KSCrashReportFilterPassthrough*) filter;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
* Passes reports to a series of subfilters, then stores the results of those operations
|
||||
* as keyed values in final master reports.
|
||||
*
|
||||
* Input: Anything
|
||||
* Output: NSDictionary
|
||||
*/
|
||||
@interface KSCrashReportFilterCombine : NSObject <KSCrashReportFilter>
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* @param firstFilter The first filter, followed by key, filter, key, ...
|
||||
* Each "filter" can be id<KSCrashReportFilter> or an NSArray
|
||||
* of filters (which gets wrapped in a pipeline filter).
|
||||
*/
|
||||
+ (KSCrashReportFilterCombine*) filterWithFiltersAndKeys:(id) firstFilter, ... NS_REQUIRES_NIL_TERMINATION;
|
||||
|
||||
/** Initializer.
|
||||
*
|
||||
* @param firstFilter The first filter, followed by key, filter, key, ...
|
||||
* Each "filter" can be id<KSCrashReportFilter> or an NSArray
|
||||
* of filters (which gets wrapped in a pipeline filter).
|
||||
*/
|
||||
- (id) initWithFiltersAndKeys:(id)firstFilter, ... NS_REQUIRES_NIL_TERMINATION;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
* A pipeline of filters. Reports get passed through each subfilter in order.
|
||||
*
|
||||
* Input: Depends on what's in the pipeline.
|
||||
* Output: Depends on what's in the pipeline.
|
||||
*/
|
||||
@interface KSCrashReportFilterPipeline : NSObject <KSCrashReportFilter>
|
||||
|
||||
/** The filters in this pipeline. */
|
||||
@property(nonatomic,readonly,retain) NSArray* filters;
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* @param firstFilter The first filter, followed by filter, filter, ...
|
||||
*/
|
||||
+ (KSCrashReportFilterPipeline*) filterWithFilters:(id) firstFilter, ... NS_REQUIRES_NIL_TERMINATION;
|
||||
|
||||
/** Initializer.
|
||||
*
|
||||
* @param firstFilter The first filter, followed by filter, filter, ...
|
||||
*/
|
||||
- (id) initWithFilters:(id) firstFilter, ... NS_REQUIRES_NIL_TERMINATION;
|
||||
|
||||
- (void) addFilter:(id<KSCrashReportFilter>) filter;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
* Extracts data associated with a key from each report.
|
||||
*/
|
||||
@interface KSCrashReportFilterObjectForKey : NSObject <KSCrashReportFilter>
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* @param key The key to search for in each report. If the key is a string,
|
||||
* it will be interpreted as a key path.
|
||||
* @param allowNotFound If NO, filtering will stop with an error if the key
|
||||
* was not found in a report.
|
||||
*/
|
||||
+ (KSCrashReportFilterObjectForKey*) filterWithKey:(id) key
|
||||
allowNotFound:(BOOL) allowNotFound;
|
||||
|
||||
/** Initializer.
|
||||
*
|
||||
* @param key The key to search for in each report. If the key is a string,
|
||||
* it will be interpreted as a key path.
|
||||
* @param allowNotFound If NO, filtering will stop with an error if the key
|
||||
* was not found in a report.
|
||||
*/
|
||||
- (id) initWithKey:(id) key
|
||||
allowNotFound:(BOOL) allowNotFound;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
* Takes values by key from the report and concatenates their string representations.
|
||||
*
|
||||
* Input: NSDictionary
|
||||
* Output: NSString
|
||||
*/
|
||||
@interface KSCrashReportFilterConcatenate : NSObject <KSCrashReportFilter>
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* @param separatorFmt Formatting text to use when separating the values. You may include
|
||||
* %@ in the formatting text to include the key name as well.
|
||||
* @param firstKey Series of keys to extract from the source report.
|
||||
*/
|
||||
+ (KSCrashReportFilterConcatenate*) filterWithSeparatorFmt:(NSString*) separatorFmt
|
||||
keys:(id) firstKey, ... NS_REQUIRES_NIL_TERMINATION;
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* @param separatorFmt Formatting text to use when separating the values. You may include
|
||||
* %@ in the formatting text to include the key name as well.
|
||||
* @param firstKey Series of keys to extract from the source report.
|
||||
*/
|
||||
- (id) initWithSeparatorFmt:(NSString*) separatorFmt
|
||||
keys:(id) firstKey, ... NS_REQUIRES_NIL_TERMINATION;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
* Fetches subsets of data from the source reports. All other data is discarded.
|
||||
*
|
||||
* Input: NSDictionary
|
||||
* Output: NSDictionary
|
||||
*/
|
||||
@interface KSCrashReportFilterSubset : NSObject <KSCrashReportFilter>
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* @param firstKeyPath Series of key paths to search in the source reports.
|
||||
*/
|
||||
+ (KSCrashReportFilterSubset*) filterWithKeys:(id) firstKeyPath, ... NS_REQUIRES_NIL_TERMINATION;
|
||||
|
||||
/** Initializer.
|
||||
*
|
||||
* @param firstKeyPath Series of key paths to search in the source reports.
|
||||
*/
|
||||
- (id) initWithKeys:(id) firstKeyPath, ... NS_REQUIRES_NIL_TERMINATION;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
* Convert UTF-8 data to an NSString.
|
||||
*
|
||||
* Input: NSData
|
||||
* Output: NSString
|
||||
*/
|
||||
@interface KSCrashReportFilterDataToString : NSObject <KSCrashReportFilter>
|
||||
|
||||
+ (KSCrashReportFilterDataToString*) filter;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
* Convert NSString to UTF-8 encoded NSData.
|
||||
*
|
||||
* Input: NSString
|
||||
* Output: NSData
|
||||
*/
|
||||
@interface KSCrashReportFilterStringToData : NSObject <KSCrashReportFilter>
|
||||
|
||||
+ (KSCrashReportFilterStringToData*) filter;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// KSCrashReportFilterGZip.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-05-10.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashReportFilter.h"
|
||||
|
||||
|
||||
/** Gzip compresses reports.
|
||||
*
|
||||
* Input: NSData
|
||||
* Output: NSData
|
||||
*/
|
||||
@interface KSCrashReportFilterGZipCompress : NSObject <KSCrashReportFilter>
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* @param compressionLevel 0 = none, 9 = best, -1 = default
|
||||
*/
|
||||
+ (KSCrashReportFilterGZipCompress*) filterWithCompressionLevel:(int) compressionLevel;
|
||||
|
||||
- (id) initWithCompressionLevel:(int) compressionLevel;
|
||||
|
||||
@end
|
||||
|
||||
/** Gzip decompresses reports.
|
||||
*
|
||||
* Input: NSData
|
||||
* Output: NSData
|
||||
*/
|
||||
@interface KSCrashReportFilterGZipDecompress : NSObject <KSCrashReportFilter>
|
||||
|
||||
+ (KSCrashReportFilterGZipDecompress*) filter;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// KSCrashReportFilterJSON.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-05-09.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashReportFilter.h"
|
||||
#import "KSJSONCodecObjC.h"
|
||||
|
||||
|
||||
/** Converts reports from dict to JSON.
|
||||
*
|
||||
* Input: NSDictionary
|
||||
* Output: NSData
|
||||
*/
|
||||
@interface KSCrashReportFilterJSONEncode : NSObject <KSCrashReportFilter>
|
||||
|
||||
+ (KSCrashReportFilterJSONEncode*) filterWithOptions:(KSJSONEncodeOption) options;
|
||||
|
||||
- (id) initWithOptions:(KSJSONEncodeOption) options;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/** Converts reports from JSON to dict.
|
||||
*
|
||||
* Input: NSData
|
||||
* Output: NSDictionary
|
||||
*/
|
||||
@interface KSCrashReportFilterJSONDecode : NSObject <KSCrashReportFilter>
|
||||
|
||||
+ (KSCrashReportFilterJSONDecode*) filterWithOptions:(KSJSONDecodeOption) options;
|
||||
|
||||
- (id) initWithOptions:(KSJSONDecodeOption) options;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// KSCrashReportFilterSets.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-08-21.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashReportFilter.h"
|
||||
#import "KSCrashReportFilterAppleFmt.h"
|
||||
|
||||
|
||||
/**
|
||||
* Common filter sets.
|
||||
*/
|
||||
@interface KSCrashFilterSets : NSObject
|
||||
|
||||
/** Create an Apple format filter that includes system and user data in JSON format.
|
||||
*/
|
||||
+ (id<KSCrashReportFilter>) appleFmtWithUserAndSystemData:(KSAppleReportStyle) reportStyle
|
||||
compressed:(BOOL) compressed;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// KSCrashReportFilterStringify.h
|
||||
// KSCrash
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashReportFilter.h"
|
||||
|
||||
/** Converts objects into strings.
|
||||
*/
|
||||
@interface KSCrashReportFilterStringify : NSObject <KSCrashReportFilter>
|
||||
|
||||
+ (KSCrashReportFilterStringify*) filter;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// KSCrashReportSinkConsole.h
|
||||
//
|
||||
// Created by Karl Stenerud on 12-05-11.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashReportFilter.h"
|
||||
|
||||
/**
|
||||
* Prints reports directly to the console.
|
||||
*
|
||||
* Input: Anything
|
||||
* Output: Same as input (passthrough)
|
||||
*/
|
||||
@interface KSCrashReportSinkConsole : NSObject <KSCrashReportFilter>
|
||||
|
||||
+ (KSCrashReportSinkConsole*) filter;
|
||||
|
||||
- (id <KSCrashReportFilter>) defaultCrashReportFilterSet;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// KSCrashReportSinkEMail.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-05-06.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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/Foundation.h>
|
||||
#import "KSCrashReportFilter.h"
|
||||
|
||||
|
||||
/** Sends reports via email.
|
||||
*
|
||||
* Input: NSData
|
||||
* Output: Same as input (passthrough)
|
||||
*/
|
||||
@interface KSCrashReportSinkEMail : NSObject <KSCrashReportFilter>
|
||||
|
||||
/**
|
||||
* @param recipients List of email addresses to send to.
|
||||
* @param subject What to put in the subject field.
|
||||
* @param message A message to accompany the reports (optional - nil = ignore).
|
||||
* @param filenameFmt How to name the attachments. You may use "%d" to differentiate
|
||||
* when multiple reports are sent at once.
|
||||
* Note: With the default filter set, files are gzipped text.
|
||||
*/
|
||||
+ (KSCrashReportSinkEMail*) sinkWithRecipients:(NSArray*) recipients
|
||||
subject:(NSString*) subject
|
||||
message:(NSString*) message
|
||||
filenameFmt:(NSString*) filenameFmt;
|
||||
|
||||
/**
|
||||
* @param recipients List of email addresses to send to.
|
||||
* @param subject What to put in the subject field.
|
||||
* @param message A message to accompany the reports (optional - nil = ignore).
|
||||
* @param filenameFmt How to name the attachments. You may use "%d" to differentiate
|
||||
* when multiple reports are sent at once.
|
||||
* Note: With the default filter set, files are gzipped text.
|
||||
*/
|
||||
- (id) initWithRecipients:(NSArray*) recipients
|
||||
subject:(NSString*) subject
|
||||
message:(NSString*) message
|
||||
filenameFmt:(NSString*) filenameFmt;
|
||||
|
||||
- (id <KSCrashReportFilter>) defaultCrashReportFilterSet;
|
||||
- (id <KSCrashReportFilter>) defaultCrashReportFilterSetAppleFmt;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// KSCrashReportSinkQuincyHockey.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-26.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashReportFilter.h"
|
||||
|
||||
|
||||
/** Sends reports to Quincy.
|
||||
*
|
||||
* Input: NSDictionary
|
||||
* Output: Same as input (passthrough)
|
||||
*/
|
||||
@interface KSCrashReportSinkQuincy : NSObject <KSCrashReportFilter>
|
||||
|
||||
/** If YES, wait until the host becomes reachable before trying to send.
|
||||
* If NO, it will attempt to send right away, and either succeed or fail.
|
||||
*
|
||||
* Default: YES
|
||||
*/
|
||||
@property(nonatomic,readwrite,assign) BOOL waitUntilReachable;
|
||||
|
||||
+ (KSCrashReportSinkQuincy*) sinkWithURL:(NSURL*) url
|
||||
userIDKey:(NSString*) userIDKey
|
||||
userNameKey:(NSString*) userNameKey
|
||||
contactEmailKey:(NSString*) contactEmailKey
|
||||
crashDescriptionKeys:(NSArray*) crashDescriptionKeys;
|
||||
|
||||
- (id) initWithURL:(NSURL*) url
|
||||
userIDKey:(NSString*) userIDKey
|
||||
userNameKey:(NSString*) userNameKey
|
||||
contactEmailKey:(NSString*) contactEmailKey
|
||||
crashDescriptionKeys:(NSArray*) crashDescriptionKeys;
|
||||
|
||||
- (id <KSCrashReportFilter>) defaultCrashReportFilterSet;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/** Sends reports to Hockey.
|
||||
*
|
||||
* Input: NSDictionary
|
||||
* Output: Same as input (passthrough)
|
||||
*/
|
||||
@interface KSCrashReportSinkHockey : KSCrashReportSinkQuincy
|
||||
|
||||
+ (KSCrashReportSinkHockey*) sinkWithAppIdentifier:(NSString*) appIdentifier
|
||||
userIDKey:(NSString*) userIDKey
|
||||
userNameKey:(NSString*) userNameKey
|
||||
contactEmailKey:(NSString*) contactEmailKey
|
||||
crashDescriptionKeys:(NSArray*) crashDescriptionKeys;
|
||||
|
||||
- (id) initWithAppIdentifier:(NSString*) appIdentifier
|
||||
userIDKey:(NSString*) userIDKey
|
||||
userNameKey:(NSString*) userNameKey
|
||||
contactEmailKey:(NSString*) contactEmailKey
|
||||
crashDescriptionKeys:(NSArray*) crashDescriptionKeys;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// KSCrashReportSinkStandard.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-18.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashReportFilter.h"
|
||||
|
||||
|
||||
/**
|
||||
* Sends crash reports to an HTTP server.
|
||||
*
|
||||
* Input: NSDictionary
|
||||
* Output: Same as input (passthrough)
|
||||
*/
|
||||
@interface KSCrashReportSinkStandard : NSObject <KSCrashReportFilter>
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* @param url The URL to connect to.
|
||||
*/
|
||||
+ (KSCrashReportSinkStandard*) sinkWithURL:(NSURL*) url;
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* @param url The URL to connect to.
|
||||
*/
|
||||
- (id) initWithURL:(NSURL*) url;
|
||||
|
||||
- (id <KSCrashReportFilter>) defaultCrashReportFilterSet;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// KSCrashReportSinkVictory.h
|
||||
//
|
||||
// Created by Kelp on 2013-03-14.
|
||||
//
|
||||
// Copyright (c) 2013 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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 "KSCrashReportFilter.h"
|
||||
|
||||
|
||||
/**
|
||||
* Sends crash reports to Victory server.
|
||||
*
|
||||
* Input: NSDictionary
|
||||
* Output: Same as input (passthrough)
|
||||
*/
|
||||
@interface KSCrashReportSinkVictory : NSObject <KSCrashReportFilter>
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* @param url The URL to connect to.
|
||||
* @param userName The user name of crash information *required. If value is nil it will be replaced with UIDevice.currentDevice.name
|
||||
* @param userEmail The user email of crash information *optional
|
||||
*/
|
||||
+ (KSCrashReportSinkVictory*) sinkWithURL:(NSURL*) url
|
||||
userName:(NSString*) userName
|
||||
userEmail:(NSString*) userEmail;;
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* @param url The URL to connect to.
|
||||
* @param userName The user name of crash information *required. If value is nil it will be replaced with UIDevice.currentDevice.name
|
||||
* @param userEmail The user email of crash information *optional
|
||||
*/
|
||||
- (id) initWithURL:(NSURL*) url
|
||||
userName:(NSString*) userName
|
||||
userEmail:(NSString*) userEmail;
|
||||
|
||||
- (id <KSCrashReportFilter>) defaultCrashReportFilterSet;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,254 @@
|
||||
//
|
||||
// KSCrashReportWriter.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-01-28.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/* Pointers to functions for writing to a crash report. All JSON types are
|
||||
* supported.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_KSCrashReportWriter_h
|
||||
#define HDR_KSCrashReportWriter_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/**
|
||||
* Encapsulates report writing functionality.
|
||||
*/
|
||||
typedef struct KSCrashReportWriter
|
||||
{
|
||||
/** Add a boolean element to the report.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*
|
||||
* @param name The name to give this element.
|
||||
*
|
||||
* @param value The value to add.
|
||||
*/
|
||||
void (*addBooleanElement)(const struct KSCrashReportWriter* writer,
|
||||
const char* name,
|
||||
bool value);
|
||||
|
||||
/** Add a floating point element to the report.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*
|
||||
* @param name The name to give this element.
|
||||
*
|
||||
* @param value The value to add.
|
||||
*/
|
||||
void (*addFloatingPointElement)(const struct KSCrashReportWriter* writer,
|
||||
const char* name,
|
||||
double value);
|
||||
|
||||
/** Add an integer element to the report.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*
|
||||
* @param name The name to give this element.
|
||||
*
|
||||
* @param value The value to add.
|
||||
*/
|
||||
void (*addIntegerElement)(const struct KSCrashReportWriter* writer,
|
||||
const char* name,
|
||||
int64_t value);
|
||||
|
||||
/** Add an unsigned integer element to the report.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*
|
||||
* @param name The name to give this element.
|
||||
*
|
||||
* @param value The value to add.
|
||||
*/
|
||||
void (*addUIntegerElement)(const struct KSCrashReportWriter* writer,
|
||||
const char* name,
|
||||
uint64_t value);
|
||||
|
||||
/** Add a string element to the report.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*
|
||||
* @param name The name to give this element.
|
||||
*
|
||||
* @param value The value to add.
|
||||
*/
|
||||
void (*addStringElement)(const struct KSCrashReportWriter* writer,
|
||||
const char* name,
|
||||
const char* value);
|
||||
|
||||
/** Add a string element from a text file to the report.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*
|
||||
* @param name The name to give this element.
|
||||
*
|
||||
* @param filePath The path to the file containing the value to add.
|
||||
*/
|
||||
void (*addTextFileElement)(const struct KSCrashReportWriter* writer,
|
||||
const char* name,
|
||||
const char* filePath);
|
||||
|
||||
/** Add an array of string elements representing lines from a text file to the report.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*
|
||||
* @param name The name to give this element.
|
||||
*
|
||||
* @param filePath The path to the file containing the value to add.
|
||||
*/
|
||||
void (*addTextFileLinesElement)(const struct KSCrashReportWriter* writer,
|
||||
const char* name,
|
||||
const char* filePath);
|
||||
|
||||
/** Add a JSON element from a text file to the report.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*
|
||||
* @param name The name to give this element.
|
||||
*
|
||||
* @param filePath The path to the file containing the value to add.
|
||||
*
|
||||
* @param closeLastContainer If false, do not close the last container.
|
||||
*/
|
||||
void (*addJSONFileElement)(const struct KSCrashReportWriter* writer,
|
||||
const char* name,
|
||||
const char* filePath,
|
||||
const bool closeLastContainer);
|
||||
|
||||
/** Add a hex encoded data element to the report.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*
|
||||
* @param name The name to give this element.
|
||||
*
|
||||
* @param value A pointer to the binary data.
|
||||
*
|
||||
* @paramn length The length of the data.
|
||||
*/
|
||||
void (*addDataElement)(const struct KSCrashReportWriter* writer,
|
||||
const char* name,
|
||||
const char* value,
|
||||
const int length);
|
||||
|
||||
/** Begin writing a hex encoded data element to the report.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*
|
||||
* @param name The name to give this element.
|
||||
*/
|
||||
void (*beginDataElement)(const struct KSCrashReportWriter* writer,
|
||||
const char* name);
|
||||
|
||||
/** Append hex encoded data to the current data element in the report.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*
|
||||
* @param value A pointer to the binary data.
|
||||
*
|
||||
* @paramn length The length of the data.
|
||||
*/
|
||||
void (*appendDataElement)(const struct KSCrashReportWriter* writer,
|
||||
const char* value,
|
||||
const int length);
|
||||
|
||||
/** Complete writing a hex encoded data element to the report.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*/
|
||||
void (*endDataElement)(const struct KSCrashReportWriter* writer);
|
||||
|
||||
/** Add a UUID element to the report.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*
|
||||
* @param name The name to give this element.
|
||||
*
|
||||
* @param value A pointer to the binary UUID data.
|
||||
*/
|
||||
void (*addUUIDElement)(const struct KSCrashReportWriter* writer,
|
||||
const char* name,
|
||||
const unsigned char* value);
|
||||
|
||||
/** Add a preformatted JSON element to the report.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*
|
||||
* @param name The name to give this element.
|
||||
*
|
||||
* @param value A pointer to the JSON data.
|
||||
*/
|
||||
void (*addJSONElement)(const struct KSCrashReportWriter* writer,
|
||||
const char* name,
|
||||
const char* jsonElement,
|
||||
bool closeLastContainer);
|
||||
|
||||
/** Begin a new object container.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*
|
||||
* @param name The name to give this element.
|
||||
*/
|
||||
void (*beginObject)(const struct KSCrashReportWriter* writer,
|
||||
const char* name);
|
||||
|
||||
/** Begin a new array container.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*
|
||||
* @param name The name to give this element.
|
||||
*/
|
||||
void (*beginArray)(const struct KSCrashReportWriter* writer,
|
||||
const char* name);
|
||||
|
||||
/** Leave the current container, returning to the next higher level
|
||||
* container.
|
||||
*
|
||||
* @param writer This writer.
|
||||
*/
|
||||
void (*endContainer)(const struct KSCrashReportWriter* writer);
|
||||
|
||||
/** Internal contextual data for the writer */
|
||||
void* context;
|
||||
|
||||
} KSCrashReportWriter;
|
||||
|
||||
typedef void (*KSReportWriteCallback)(const KSCrashReportWriter* writer);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSCrashReportWriter_h
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
//
|
||||
// KSJSONCodecObjC.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-01-08.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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/Foundation.h>
|
||||
|
||||
|
||||
/** Optional behavior when encoding JSON data */
|
||||
typedef enum
|
||||
{
|
||||
KSJSONEncodeOptionNone = 0,
|
||||
|
||||
/** Indent 4 spaces per object/array level */
|
||||
KSJSONEncodeOptionPretty = 1,
|
||||
|
||||
/** Sort object contents by key name */
|
||||
KSJSONEncodeOptionSorted = 2,
|
||||
} KSJSONEncodeOption;
|
||||
|
||||
|
||||
/** Optional behavior when decoding JSON data */
|
||||
typedef enum
|
||||
{
|
||||
KSJSONDecodeOptionNone = 0,
|
||||
|
||||
/** Normally, null elements get stored as [NSNull null].
|
||||
* If this option is set, do not store anything when a null element is
|
||||
* encountered inside an array.
|
||||
*/
|
||||
KSJSONDecodeOptionIgnoreNullInArray = 1,
|
||||
|
||||
/** Normally, null elements get stored as [NSNull null].
|
||||
* If this option is set, do not store anything when a null element is
|
||||
* encountered inside an object.
|
||||
*/
|
||||
KSJSONDecodeOptionIgnoreNullInObject = 2,
|
||||
|
||||
/** Convenience enum to ignore nulls in arrays and objects. */
|
||||
KSJSONDecodeOptionIgnoreAllNulls = 3,
|
||||
|
||||
/** If an error is encountered, return the partially decoded object. */
|
||||
KSJSONDecodeOptionKeepPartialObject = 4,
|
||||
} KSJSONDecodeOption;
|
||||
|
||||
|
||||
/**
|
||||
* Encodes and decodes UTF-8 JSON data.
|
||||
*/
|
||||
@interface KSJSONCodec : NSObject
|
||||
|
||||
/** Encode an object to JSON data.
|
||||
*
|
||||
* @param object The array or dictionary to encode.
|
||||
*
|
||||
* @param options Options for how to encode the data.
|
||||
*
|
||||
* @param error Place to store any error that occurs (nil = ignore). Will be
|
||||
* set to nil on success.
|
||||
*
|
||||
* @return The encoded UTF-8 JSON data or nil if an error occurred.
|
||||
*/
|
||||
+ (NSData*) encode:(id) object
|
||||
options:(KSJSONEncodeOption) options
|
||||
error:(NSError**) error;
|
||||
|
||||
/** Decode JSON data to an object.
|
||||
*
|
||||
* @param JSONData The UTF-8 data to decode.
|
||||
*
|
||||
* @param options Options for how to decode the data.
|
||||
*
|
||||
* @param error Place to store any error that occurs (nil = ignore). Will be
|
||||
* set to nil on success.
|
||||
*
|
||||
* @return The decoded object or, if the KSJSONDecodeOptionKeepPartialFile
|
||||
* option is not set, nil when an error occurs.
|
||||
*/
|
||||
+ (id) decode:(NSData*) JSONData
|
||||
options:(KSJSONDecodeOption) options
|
||||
error:(NSError**) error;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,144 @@
|
||||
//
|
||||
// KSMachineContext.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2016-12-02.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
#ifndef HDR_KSMachineContext_h
|
||||
#define HDR_KSMachineContext_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "KSThread.h"
|
||||
#include <stdbool.h>
|
||||
#include <mach/mach.h>
|
||||
|
||||
/** Suspend the runtime environment.
|
||||
*/
|
||||
void ksmc_suspendEnvironment(thread_act_array_t *suspendedThreads, mach_msg_type_number_t *numSuspendedThreads);
|
||||
|
||||
/** Resume the runtime environment.
|
||||
*/
|
||||
void ksmc_resumeEnvironment(thread_act_array_t threads, mach_msg_type_number_t numThreads);
|
||||
|
||||
/** Create a new machine context on the stack.
|
||||
* This macro creates a storage object on the stack, as well as a pointer of type
|
||||
* struct KSMachineContext* in the current scope, which points to the storage object.
|
||||
*
|
||||
* Example usage: KSMC_NEW_CONTEXT(a_context);
|
||||
* This creates a new pointer at the current scope that behaves as if:
|
||||
* struct KSMachineContext* a_context = some_storage_location;
|
||||
*
|
||||
* @param NAME The C identifier to give the pointer.
|
||||
*/
|
||||
#define KSMC_NEW_CONTEXT(NAME) \
|
||||
char ksmc_##NAME##_storage[ksmc_contextSize()]; \
|
||||
struct KSMachineContext* NAME = (struct KSMachineContext*)ksmc_##NAME##_storage
|
||||
|
||||
struct KSMachineContext;
|
||||
|
||||
/** Get the internal size of a machine context.
|
||||
*/
|
||||
int ksmc_contextSize(void);
|
||||
|
||||
/** Fill in a machine context from a thread.
|
||||
*
|
||||
* @param thread The thread to get information from.
|
||||
* @param destinationContext The context to fill.
|
||||
* @param isCrashedContext Used to indicate that this is the thread that crashed,
|
||||
*
|
||||
* @return true if successful.
|
||||
*/
|
||||
bool ksmc_getContextForThread(KSThread thread, struct KSMachineContext* destinationContext, bool isCrashedContext);
|
||||
|
||||
/** Fill in a machine context from a signal handler.
|
||||
* A signal handler context is always assumed to be a crashed context.
|
||||
*
|
||||
* @param signalUserContext The signal context to get information from.
|
||||
* @param destinationContext The context to fill.
|
||||
*
|
||||
* @return true if successful.
|
||||
*/
|
||||
bool ksmc_getContextForSignal(void* signalUserContext, struct KSMachineContext* destinationContext);
|
||||
|
||||
/** Get the thread associated with a machine context.
|
||||
*
|
||||
* @param context The machine context.
|
||||
*
|
||||
* @return The associated thread.
|
||||
*/
|
||||
KSThread ksmc_getThreadFromContext(const struct KSMachineContext* const context);
|
||||
|
||||
/** Get the number of threads stored in a machine context.
|
||||
*
|
||||
* @param context The machine context.
|
||||
*
|
||||
* @return The number of threads.
|
||||
*/
|
||||
int ksmc_getThreadCount(const struct KSMachineContext* const context);
|
||||
|
||||
/** Get a thread from a machine context.
|
||||
*
|
||||
* @param context The machine context.
|
||||
* @param index The index of the thread to retrieve.
|
||||
*
|
||||
* @return The thread.
|
||||
*/
|
||||
KSThread ksmc_getThreadAtIndex(const struct KSMachineContext* const context, int index);
|
||||
|
||||
/** Get the index of a thread.
|
||||
*
|
||||
* @param context The machine context.
|
||||
* @param thread The thread.
|
||||
*
|
||||
* @return The thread's index, or -1 if it couldn't be determined.
|
||||
*/
|
||||
int ksmc_indexOfThread(const struct KSMachineContext* const context, KSThread thread);
|
||||
|
||||
/** Check if this is a crashed context.
|
||||
*/
|
||||
bool ksmc_isCrashedContext(const struct KSMachineContext* const context);
|
||||
|
||||
/** Check if this context can have stored CPU state.
|
||||
*/
|
||||
bool ksmc_canHaveCPUState(const struct KSMachineContext* const context);
|
||||
|
||||
/** Check if this context has valid exception registers.
|
||||
*/
|
||||
bool ksmc_hasValidExceptionRegisters(const struct KSMachineContext* const context);
|
||||
|
||||
/** Add a thread to the reserved threads list.
|
||||
*
|
||||
* @param thread The thread to add to the list.
|
||||
*/
|
||||
void ksmc_addReservedThread(KSThread thread);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSMachineContext_h
|
||||
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// KSThread.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-01-29.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef HDR_KSThread_h
|
||||
#define HDR_KSThread_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
typedef uintptr_t KSThread;
|
||||
|
||||
/** Get a thread's name. Internally, a thread name will
|
||||
* never be more than 64 characters long.
|
||||
*
|
||||
* @param thread The thread whose name to get.
|
||||
*
|
||||
* @oaram buffer Buffer to hold the name.
|
||||
*
|
||||
* @param bufLength The length of the buffer.
|
||||
*
|
||||
* @return true if a name was found.
|
||||
*/
|
||||
bool ksthread_getThreadName(const KSThread thread, char* const buffer, int bufLength);
|
||||
|
||||
/** Get the name of a thread's dispatch queue. Internally, a queue name will
|
||||
* never be more than 64 characters long.
|
||||
*
|
||||
* @param thread The thread whose queue name to get.
|
||||
*
|
||||
* @oaram buffer Buffer to hold the name.
|
||||
*
|
||||
* @param bufLength The length of the buffer.
|
||||
*
|
||||
* @return true if a name or label was found.
|
||||
*/
|
||||
bool ksthread_getQueueName(KSThread thread, char* buffer, int bufLength);
|
||||
|
||||
/* Get the current mach thread ID.
|
||||
* mach_thread_self() receives a send right for the thread port which needs to
|
||||
* be deallocated to balance the reference count. This function takes care of
|
||||
* all of that for you.
|
||||
*
|
||||
* @return The current thread ID.
|
||||
*/
|
||||
KSThread ksthread_self(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSThread_h
|
||||
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// NSData+GZip.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-19.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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/Foundation.h>
|
||||
|
||||
|
||||
/**
|
||||
* GNU zip/unzip support for NSData.
|
||||
*/
|
||||
@interface NSData (KSGZip)
|
||||
|
||||
/**
|
||||
* Gzip the data in this object (no header).
|
||||
*
|
||||
* @param compressionLevel The GZip compression level to use:
|
||||
* 0 = no compression.
|
||||
* 1 = best speed.
|
||||
* 9 = best compression.
|
||||
* -1 = default.
|
||||
*
|
||||
* @param error (optional) Set to any error that occurs, or nil if no error.
|
||||
* Pass nil to ignore.
|
||||
*
|
||||
* @return A new NSData with the gzipped contents of this object.
|
||||
*/
|
||||
- (NSData*) gzippedWithCompressionLevel:(int) compressionLevel
|
||||
error:(NSError**) error;
|
||||
|
||||
/**
|
||||
* Gunzip the data in this object (no header).
|
||||
*
|
||||
* @param error (optional) Set to any error that occurs, or nil if no error.
|
||||
* Pass nil to ignore.
|
||||
*
|
||||
* @return A new NSData with the gunzipped contents of this object.
|
||||
*/
|
||||
- (NSData*) gunzippedWithError:(NSError**) error;
|
||||
|
||||
@end
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
framework module KSCrash {
|
||||
umbrella header "KSCrashFramework.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
//===--- AlignOf.h - Portable calculation of type alignment -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the AlignOf function that computes alignments for
|
||||
// arbitrary types.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_ALIGNOF_H
|
||||
#define LLVM_SUPPORT_ALIGNOF_H
|
||||
|
||||
#include "Compiler.h"
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// For everything other than an abstract class we can calulate alignment by
|
||||
// building a class with a single character and a member of the given type.
|
||||
template <typename T, bool = std::is_abstract<T>::value>
|
||||
struct AlignmentCalcImpl {
|
||||
char x;
|
||||
#if defined(_MSC_VER)
|
||||
// Disables "structure was padded due to __declspec(align())" warnings that are
|
||||
// generated by any class using AlignOf<T> with a manually specified alignment.
|
||||
// Although the warning is disabled in the LLVM project we need this pragma
|
||||
// as AlignOf.h is a published support header that's available for use
|
||||
// out-of-tree, and we would like that to compile cleanly at /W4.
|
||||
#pragma warning(suppress : 4324)
|
||||
#endif
|
||||
T t;
|
||||
private:
|
||||
AlignmentCalcImpl() = delete;
|
||||
};
|
||||
|
||||
// Abstract base class helper, this will have the minimal alignment and size
|
||||
// for any abstract class. We don't even define its destructor because this
|
||||
// type should never be used in a way that requires it.
|
||||
struct AlignmentCalcImplBase {
|
||||
virtual ~AlignmentCalcImplBase() = 0;
|
||||
};
|
||||
|
||||
// When we have an abstract class type, specialize the alignment computation
|
||||
// engine to create another abstract class that derives from both an empty
|
||||
// abstract base class and the provided type. This has the same effect as the
|
||||
// above except that it handles the fact that we can't actually create a member
|
||||
// of type T.
|
||||
template <typename T>
|
||||
struct AlignmentCalcImpl<T, true> : AlignmentCalcImplBase, T {
|
||||
~AlignmentCalcImpl() override = 0;
|
||||
};
|
||||
|
||||
} // End detail namespace.
|
||||
|
||||
/// AlignOf - A templated class that contains an enum value representing
|
||||
/// the alignment of the template argument. For example,
|
||||
/// AlignOf<int>::Alignment represents the alignment of type "int". The
|
||||
/// alignment calculated is the minimum alignment, and not necessarily
|
||||
/// the "desired" alignment returned by GCC's __alignof__ (for example). Note
|
||||
/// that because the alignment is an enum value, it can be used as a
|
||||
/// compile-time constant (e.g., for template instantiation).
|
||||
template <typename T>
|
||||
struct AlignOf {
|
||||
#ifndef _MSC_VER
|
||||
// Avoid warnings from GCC like:
|
||||
// comparison between 'enum llvm::AlignOf<X>::<anonymous>' and 'enum
|
||||
// llvm::AlignOf<Y>::<anonymous>' [-Wenum-compare]
|
||||
// by using constexpr instead of enum.
|
||||
// (except on MSVC, since it doesn't support constexpr yet).
|
||||
static constexpr unsigned Alignment = static_cast<unsigned int>(
|
||||
sizeof(detail::AlignmentCalcImpl<T>) - sizeof(T));
|
||||
#else
|
||||
enum {
|
||||
Alignment = static_cast<unsigned int>(
|
||||
sizeof(::llvm::detail::AlignmentCalcImpl<T>) - sizeof(T))
|
||||
};
|
||||
#endif
|
||||
enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 };
|
||||
enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 };
|
||||
enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 };
|
||||
enum { Alignment_GreaterEqual_16Bytes = Alignment >= 16 ? 1 : 0 };
|
||||
|
||||
enum { Alignment_LessEqual_2Bytes = Alignment <= 2 ? 1 : 0 };
|
||||
enum { Alignment_LessEqual_4Bytes = Alignment <= 4 ? 1 : 0 };
|
||||
enum { Alignment_LessEqual_8Bytes = Alignment <= 8 ? 1 : 0 };
|
||||
enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 };
|
||||
};
|
||||
|
||||
#ifndef _MSC_VER
|
||||
template <typename T> constexpr unsigned AlignOf<T>::Alignment;
|
||||
#endif
|
||||
|
||||
/// alignOf - A templated function that returns the minimum alignment of
|
||||
/// of a type. This provides no extra functionality beyond the AlignOf
|
||||
/// class besides some cosmetic cleanliness. Example usage:
|
||||
/// alignOf<int>() returns the alignment of an int.
|
||||
template <typename T>
|
||||
inline unsigned alignOf() { return AlignOf<T>::Alignment; }
|
||||
|
||||
/// \struct AlignedCharArray
|
||||
/// \brief Helper for building an aligned character array type.
|
||||
///
|
||||
/// This template is used to explicitly build up a collection of aligned
|
||||
/// character array types. We have to build these up using a macro and explicit
|
||||
/// specialization to cope with old versions of MSVC and GCC where only an
|
||||
/// integer literal can be used to specify an alignment constraint. Once built
|
||||
/// up here, we can then begin to indirect between these using normal C++
|
||||
/// template parameters.
|
||||
|
||||
// MSVC requires special handling here.
|
||||
#ifndef _MSC_VER
|
||||
|
||||
#if __has_feature(cxx_alignas)
|
||||
template<std::size_t Alignment, std::size_t Size>
|
||||
struct AlignedCharArray {
|
||||
alignas(Alignment) char buffer[Size];
|
||||
};
|
||||
|
||||
#elif defined(__GNUC__) || defined(__IBM_ATTRIBUTES)
|
||||
/// \brief Create a type with an aligned char buffer.
|
||||
template<std::size_t Alignment, std::size_t Size>
|
||||
struct AlignedCharArray;
|
||||
|
||||
#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
|
||||
template<std::size_t Size> \
|
||||
struct AlignedCharArray<x, Size> { \
|
||||
__attribute__((aligned(x))) char buffer[Size]; \
|
||||
};
|
||||
|
||||
LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1)
|
||||
LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2)
|
||||
LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4)
|
||||
LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8)
|
||||
LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16)
|
||||
LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32)
|
||||
LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64)
|
||||
LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128)
|
||||
|
||||
#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
|
||||
|
||||
#else
|
||||
# error No supported align as directive.
|
||||
#endif
|
||||
|
||||
#else // _MSC_VER
|
||||
|
||||
/// \brief Create a type with an aligned char buffer.
|
||||
template<std::size_t Alignment, std::size_t Size>
|
||||
struct AlignedCharArray;
|
||||
|
||||
// We provide special variations of this template for the most common
|
||||
// alignments because __declspec(align(...)) doesn't actually work when it is
|
||||
// a member of a by-value function argument in MSVC, even if the alignment
|
||||
// request is something reasonably like 8-byte or 16-byte. Note that we can't
|
||||
// even include the declspec with the union that forces the alignment because
|
||||
// MSVC warns on the existence of the declspec despite the union member forcing
|
||||
// proper alignment.
|
||||
|
||||
template<std::size_t Size>
|
||||
struct AlignedCharArray<1, Size> {
|
||||
union {
|
||||
char aligned;
|
||||
char buffer[Size];
|
||||
};
|
||||
};
|
||||
|
||||
template<std::size_t Size>
|
||||
struct AlignedCharArray<2, Size> {
|
||||
union {
|
||||
short aligned;
|
||||
char buffer[Size];
|
||||
};
|
||||
};
|
||||
|
||||
template<std::size_t Size>
|
||||
struct AlignedCharArray<4, Size> {
|
||||
union {
|
||||
int aligned;
|
||||
char buffer[Size];
|
||||
};
|
||||
};
|
||||
|
||||
template<std::size_t Size>
|
||||
struct AlignedCharArray<8, Size> {
|
||||
union {
|
||||
double aligned;
|
||||
char buffer[Size];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// The rest of these are provided with a __declspec(align(...)) and we simply
|
||||
// can't pass them by-value as function arguments on MSVC.
|
||||
|
||||
#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
|
||||
template<std::size_t Size> \
|
||||
struct AlignedCharArray<x, Size> { \
|
||||
__declspec(align(x)) char buffer[Size]; \
|
||||
};
|
||||
|
||||
LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16)
|
||||
LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32)
|
||||
LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64)
|
||||
LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128)
|
||||
|
||||
#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
namespace detail {
|
||||
template <typename T1,
|
||||
typename T2 = char, typename T3 = char, typename T4 = char,
|
||||
typename T5 = char, typename T6 = char, typename T7 = char,
|
||||
typename T8 = char, typename T9 = char, typename T10 = char>
|
||||
class AlignerImpl {
|
||||
T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10;
|
||||
|
||||
AlignerImpl() = delete;
|
||||
};
|
||||
|
||||
template <typename T1,
|
||||
typename T2 = char, typename T3 = char, typename T4 = char,
|
||||
typename T5 = char, typename T6 = char, typename T7 = char,
|
||||
typename T8 = char, typename T9 = char, typename T10 = char>
|
||||
union SizerImpl {
|
||||
char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)],
|
||||
arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)], arr8[sizeof(T8)],
|
||||
arr9[sizeof(T9)], arr10[sizeof(T10)];
|
||||
};
|
||||
} // end namespace detail
|
||||
|
||||
/// \brief This union template exposes a suitably aligned and sized character
|
||||
/// array member which can hold elements of any of up to ten types.
|
||||
///
|
||||
/// These types may be arrays, structs, or any other types. The goal is to
|
||||
/// expose a char array buffer member which can be used as suitable storage for
|
||||
/// a placement new of any of these types. Support for more than ten types can
|
||||
/// be added at the cost of more boilerplate.
|
||||
template <typename T1,
|
||||
typename T2 = char, typename T3 = char, typename T4 = char,
|
||||
typename T5 = char, typename T6 = char, typename T7 = char,
|
||||
typename T8 = char, typename T9 = char, typename T10 = char>
|
||||
struct AlignedCharArrayUnion : llvm::AlignedCharArray<
|
||||
AlignOf<llvm::detail::AlignerImpl<T1, T2, T3, T4, T5,
|
||||
T6, T7, T8, T9, T10> >::Alignment,
|
||||
sizeof(::llvm::detail::SizerImpl<T1, T2, T3, T4, T5,
|
||||
T6, T7, T8, T9, T10>)> {
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_SUPPORT_ALIGNOF_H
|
||||
@@ -0,0 +1,326 @@
|
||||
//===-- llvm/Support/Casting.h - Allow flexible, checked, casts -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the isa<X>(), cast<X>(), dyn_cast<X>(), cast_or_null<X>(),
|
||||
// and dyn_cast_or_null<X>() templates.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_CASTING_H
|
||||
#define LLVM_SUPPORT_CASTING_H
|
||||
|
||||
#include "Compiler.h"
|
||||
#include "type_traits.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// isa<x> Support Templates
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Define a template that can be specialized by smart pointers to reflect the
|
||||
// fact that they are automatically dereferenced, and are not involved with the
|
||||
// template selection process... the default implementation is a noop.
|
||||
//
|
||||
template<typename From> struct simplify_type {
|
||||
typedef From SimpleType; // The real type this represents...
|
||||
|
||||
// An accessor to get the real value...
|
||||
static SimpleType &getSimplifiedValue(From &Val) { return Val; }
|
||||
};
|
||||
|
||||
template<typename From> struct simplify_type<const From> {
|
||||
typedef typename simplify_type<From>::SimpleType NonConstSimpleType;
|
||||
typedef typename add_const_past_pointer<NonConstSimpleType>::type
|
||||
SimpleType;
|
||||
typedef typename add_lvalue_reference_if_not_pointer<SimpleType>::type
|
||||
RetType;
|
||||
static RetType getSimplifiedValue(const From& Val) {
|
||||
return simplify_type<From>::getSimplifiedValue(const_cast<From&>(Val));
|
||||
}
|
||||
};
|
||||
|
||||
// The core of the implementation of isa<X> is here; To and From should be
|
||||
// the names of classes. This template can be specialized to customize the
|
||||
// implementation of isa<> without rewriting it from scratch.
|
||||
template <typename To, typename From, typename Enabler = void>
|
||||
struct isa_impl {
|
||||
static inline bool doit(const From &Val) {
|
||||
return To::classof(&Val);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Always allow upcasts, and perform no dynamic check for them.
|
||||
template <typename To, typename From>
|
||||
struct isa_impl<
|
||||
To, From, typename std::enable_if<std::is_base_of<To, From>::value>::type> {
|
||||
static inline bool doit(const From &) { return true; }
|
||||
};
|
||||
|
||||
template <typename To, typename From> struct isa_impl_cl {
|
||||
static inline bool doit(const From &Val) {
|
||||
return isa_impl<To, From>::doit(Val);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename To, typename From> struct isa_impl_cl<To, const From> {
|
||||
static inline bool doit(const From &Val) {
|
||||
return isa_impl<To, From>::doit(Val);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename To, typename From> struct isa_impl_cl<To, From*> {
|
||||
static inline bool doit(const From *Val) {
|
||||
assert(Val && "isa<> used on a null pointer");
|
||||
return isa_impl<To, From>::doit(*Val);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename To, typename From> struct isa_impl_cl<To, From*const> {
|
||||
static inline bool doit(const From *Val) {
|
||||
assert(Val && "isa<> used on a null pointer");
|
||||
return isa_impl<To, From>::doit(*Val);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename To, typename From> struct isa_impl_cl<To, const From*> {
|
||||
static inline bool doit(const From *Val) {
|
||||
assert(Val && "isa<> used on a null pointer");
|
||||
return isa_impl<To, From>::doit(*Val);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename To, typename From> struct isa_impl_cl<To, const From*const> {
|
||||
static inline bool doit(const From *Val) {
|
||||
assert(Val && "isa<> used on a null pointer");
|
||||
return isa_impl<To, From>::doit(*Val);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, typename From, typename SimpleFrom>
|
||||
struct isa_impl_wrap {
|
||||
// When From != SimplifiedType, we can simplify the type some more by using
|
||||
// the simplify_type template.
|
||||
static bool doit(const From &Val) {
|
||||
return isa_impl_wrap<To, SimpleFrom,
|
||||
typename simplify_type<SimpleFrom>::SimpleType>::doit(
|
||||
simplify_type<const From>::getSimplifiedValue(Val));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, typename FromTy>
|
||||
struct isa_impl_wrap<To, FromTy, FromTy> {
|
||||
// When From == SimpleType, we are as simple as we are going to get.
|
||||
static bool doit(const FromTy &Val) {
|
||||
return isa_impl_cl<To,FromTy>::doit(Val);
|
||||
}
|
||||
};
|
||||
|
||||
// isa<X> - Return true if the parameter to the template is an instance of the
|
||||
// template type argument. Used like this:
|
||||
//
|
||||
// if (isa<Type>(myVal)) { ... }
|
||||
//
|
||||
template <class X, class Y>
|
||||
LLVM_ATTRIBUTE_UNUSED_RESULT inline bool isa(const Y &Val) {
|
||||
return isa_impl_wrap<X, const Y,
|
||||
typename simplify_type<const Y>::SimpleType>::doit(Val);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// cast<x> Support Templates
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
template<class To, class From> struct cast_retty;
|
||||
|
||||
|
||||
// Calculate what type the 'cast' function should return, based on a requested
|
||||
// type of To and a source type of From.
|
||||
template<class To, class From> struct cast_retty_impl {
|
||||
typedef To& ret_type; // Normal case, return Ty&
|
||||
};
|
||||
template<class To, class From> struct cast_retty_impl<To, const From> {
|
||||
typedef const To &ret_type; // Normal case, return Ty&
|
||||
};
|
||||
|
||||
template<class To, class From> struct cast_retty_impl<To, From*> {
|
||||
typedef To* ret_type; // Pointer arg case, return Ty*
|
||||
};
|
||||
|
||||
template<class To, class From> struct cast_retty_impl<To, const From*> {
|
||||
typedef const To* ret_type; // Constant pointer arg case, return const Ty*
|
||||
};
|
||||
|
||||
template<class To, class From> struct cast_retty_impl<To, const From*const> {
|
||||
typedef const To* ret_type; // Constant pointer arg case, return const Ty*
|
||||
};
|
||||
|
||||
|
||||
template<class To, class From, class SimpleFrom>
|
||||
struct cast_retty_wrap {
|
||||
// When the simplified type and the from type are not the same, use the type
|
||||
// simplifier to reduce the type, then reuse cast_retty_impl to get the
|
||||
// resultant type.
|
||||
typedef typename cast_retty<To, SimpleFrom>::ret_type ret_type;
|
||||
};
|
||||
|
||||
template<class To, class FromTy>
|
||||
struct cast_retty_wrap<To, FromTy, FromTy> {
|
||||
// When the simplified type is equal to the from type, use it directly.
|
||||
typedef typename cast_retty_impl<To,FromTy>::ret_type ret_type;
|
||||
};
|
||||
|
||||
template<class To, class From>
|
||||
struct cast_retty {
|
||||
typedef typename cast_retty_wrap<To, From,
|
||||
typename simplify_type<From>::SimpleType>::ret_type ret_type;
|
||||
};
|
||||
|
||||
// Ensure the non-simple values are converted using the simplify_type template
|
||||
// that may be specialized by smart pointers...
|
||||
//
|
||||
template<class To, class From, class SimpleFrom> struct cast_convert_val {
|
||||
// This is not a simple type, use the template to simplify it...
|
||||
static typename cast_retty<To, From>::ret_type doit(From &Val) {
|
||||
return cast_convert_val<To, SimpleFrom,
|
||||
typename simplify_type<SimpleFrom>::SimpleType>::doit(
|
||||
simplify_type<From>::getSimplifiedValue(Val));
|
||||
}
|
||||
};
|
||||
|
||||
template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> {
|
||||
// This _is_ a simple type, just cast it.
|
||||
static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) {
|
||||
typename cast_retty<To, FromTy>::ret_type Res2
|
||||
= (typename cast_retty<To, FromTy>::ret_type)const_cast<FromTy&>(Val);
|
||||
return Res2;
|
||||
}
|
||||
};
|
||||
|
||||
template <class X> struct is_simple_type {
|
||||
static const bool value =
|
||||
std::is_same<X, typename simplify_type<X>::SimpleType>::value;
|
||||
};
|
||||
|
||||
// cast<X> - Return the argument parameter cast to the specified type. This
|
||||
// casting operator asserts that the type is correct, so it does not return null
|
||||
// on failure. It does not allow a null argument (use cast_or_null for that).
|
||||
// It is typically used like this:
|
||||
//
|
||||
// cast<Instruction>(myVal)->getParent()
|
||||
//
|
||||
template <class X, class Y>
|
||||
inline typename std::enable_if<!is_simple_type<Y>::value,
|
||||
typename cast_retty<X, const Y>::ret_type>::type
|
||||
cast(const Y &Val) {
|
||||
assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!");
|
||||
return cast_convert_val<
|
||||
X, const Y, typename simplify_type<const Y>::SimpleType>::doit(Val);
|
||||
}
|
||||
|
||||
template <class X, class Y>
|
||||
inline typename cast_retty<X, Y>::ret_type cast(Y &Val) {
|
||||
assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!");
|
||||
return cast_convert_val<X, Y,
|
||||
typename simplify_type<Y>::SimpleType>::doit(Val);
|
||||
}
|
||||
|
||||
template <class X, class Y>
|
||||
inline typename cast_retty<X, Y *>::ret_type cast(Y *Val) {
|
||||
assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!");
|
||||
return cast_convert_val<X, Y*,
|
||||
typename simplify_type<Y*>::SimpleType>::doit(Val);
|
||||
}
|
||||
|
||||
// cast_or_null<X> - Functionally identical to cast, except that a null value is
|
||||
// accepted.
|
||||
//
|
||||
template <class X, class Y>
|
||||
LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
|
||||
!is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type
|
||||
cast_or_null(const Y &Val) {
|
||||
if (!Val)
|
||||
return nullptr;
|
||||
assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
|
||||
return cast<X>(Val);
|
||||
}
|
||||
|
||||
template <class X, class Y>
|
||||
LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
|
||||
!is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type
|
||||
cast_or_null(Y &Val) {
|
||||
if (!Val)
|
||||
return nullptr;
|
||||
assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
|
||||
return cast<X>(Val);
|
||||
}
|
||||
|
||||
template <class X, class Y>
|
||||
LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type
|
||||
cast_or_null(Y *Val) {
|
||||
if (!Val) return nullptr;
|
||||
assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
|
||||
return cast<X>(Val);
|
||||
}
|
||||
|
||||
|
||||
// dyn_cast<X> - Return the argument parameter cast to the specified type. This
|
||||
// casting operator returns null if the argument is of the wrong type, so it can
|
||||
// be used to test for a type as well as cast if successful. This should be
|
||||
// used in the context of an if statement like this:
|
||||
//
|
||||
// if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... }
|
||||
//
|
||||
|
||||
template <class X, class Y>
|
||||
LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
|
||||
!is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type
|
||||
dyn_cast(const Y &Val) {
|
||||
return isa<X>(Val) ? cast<X>(Val) : nullptr;
|
||||
}
|
||||
|
||||
template <class X, class Y>
|
||||
LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y>::ret_type
|
||||
dyn_cast(Y &Val) {
|
||||
return isa<X>(Val) ? cast<X>(Val) : nullptr;
|
||||
}
|
||||
|
||||
template <class X, class Y>
|
||||
LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type
|
||||
dyn_cast(Y *Val) {
|
||||
return isa<X>(Val) ? cast<X>(Val) : nullptr;
|
||||
}
|
||||
|
||||
// dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null
|
||||
// value is accepted.
|
||||
//
|
||||
template <class X, class Y>
|
||||
LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
|
||||
!is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type
|
||||
dyn_cast_or_null(const Y &Val) {
|
||||
return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
|
||||
}
|
||||
|
||||
template <class X, class Y>
|
||||
LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
|
||||
!is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type
|
||||
dyn_cast_or_null(Y &Val) {
|
||||
return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
|
||||
}
|
||||
|
||||
template <class X, class Y>
|
||||
LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type
|
||||
dyn_cast_or_null(Y *Val) {
|
||||
return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,448 @@
|
||||
//===-- llvm/Support/Compiler.h - Compiler abstraction support --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines several macros, based on the current compiler. This allows
|
||||
// use of compiler-specific features in a way that remains portable.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_COMPILER_H
|
||||
#define LLVM_SUPPORT_COMPILER_H
|
||||
|
||||
#include "llvm-config.h"
|
||||
|
||||
#ifndef __has_feature
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef __has_extension
|
||||
# define __has_extension(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef __has_attribute
|
||||
# define __has_attribute(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef __has_builtin
|
||||
# define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
/// \macro LLVM_GNUC_PREREQ
|
||||
/// \brief Extend the default __GNUC_PREREQ even if glibc's features.h isn't
|
||||
/// available.
|
||||
#ifndef LLVM_GNUC_PREREQ
|
||||
# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
|
||||
# define LLVM_GNUC_PREREQ(maj, min, patch) \
|
||||
((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \
|
||||
((maj) << 20) + ((min) << 10) + (patch))
|
||||
# elif defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
# define LLVM_GNUC_PREREQ(maj, min, patch) \
|
||||
((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
|
||||
# else
|
||||
# define LLVM_GNUC_PREREQ(maj, min, patch) 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/// \macro LLVM_MSC_PREREQ
|
||||
/// \brief Is the compiler MSVC of at least the specified version?
|
||||
/// The common \param version values to check for are:
|
||||
/// * 1800: Microsoft Visual Studio 2013 / 12.0
|
||||
/// * 1900: Microsoft Visual Studio 2015 / 14.0
|
||||
#ifdef _MSC_VER
|
||||
#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version))
|
||||
|
||||
// We require at least MSVC 2013.
|
||||
#if !LLVM_MSC_PREREQ(1800)
|
||||
#error LLVM requires at least MSVC 2013.
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define LLVM_MSC_PREREQ(version) 0
|
||||
#endif
|
||||
|
||||
#if !defined(_MSC_VER) || defined(__clang__) || LLVM_MSC_PREREQ(1900)
|
||||
#define LLVM_NOEXCEPT noexcept
|
||||
#else
|
||||
#define LLVM_NOEXCEPT throw()
|
||||
#endif
|
||||
|
||||
/// \brief Does the compiler support ref-qualifiers for *this?
|
||||
///
|
||||
/// Sadly, this is separate from just rvalue reference support because GCC
|
||||
/// and MSVC implemented this later than everything else.
|
||||
#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1)
|
||||
#define LLVM_HAS_RVALUE_REFERENCE_THIS 1
|
||||
#else
|
||||
#define LLVM_HAS_RVALUE_REFERENCE_THIS 0
|
||||
#endif
|
||||
|
||||
/// Expands to '&' if ref-qualifiers for *this are supported.
|
||||
///
|
||||
/// This can be used to provide lvalue/rvalue overrides of member functions.
|
||||
/// The rvalue override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS
|
||||
#if LLVM_HAS_RVALUE_REFERENCE_THIS
|
||||
#define LLVM_LVALUE_FUNCTION &
|
||||
#else
|
||||
#define LLVM_LVALUE_FUNCTION
|
||||
#endif
|
||||
|
||||
#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
# define LLVM_CONSTEXPR constexpr
|
||||
#else
|
||||
# define LLVM_CONSTEXPR
|
||||
#endif
|
||||
|
||||
/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked
|
||||
/// into a shared library, then the class should be private to the library and
|
||||
/// not accessible from outside it. Can also be used to mark variables and
|
||||
/// functions, making them private to any shared library they are linked into.
|
||||
/// On PE/COFF targets, library visibility is the default, so this isn't needed.
|
||||
#if (__has_attribute(visibility) || LLVM_GNUC_PREREQ(4, 0, 0)) && \
|
||||
!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32)
|
||||
#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden")))
|
||||
#else
|
||||
#define LLVM_LIBRARY_VISIBILITY
|
||||
#endif
|
||||
|
||||
#if __has_attribute(sentinel) || LLVM_GNUC_PREREQ(3, 0, 0)
|
||||
#define LLVM_END_WITH_NULL __attribute__((sentinel))
|
||||
#else
|
||||
#define LLVM_END_WITH_NULL
|
||||
#endif
|
||||
|
||||
#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0)
|
||||
#define LLVM_ATTRIBUTE_USED __attribute__((__used__))
|
||||
#else
|
||||
#define LLVM_ATTRIBUTE_USED
|
||||
#endif
|
||||
|
||||
#if __has_attribute(warn_unused_result) || LLVM_GNUC_PREREQ(3, 4, 0)
|
||||
#define LLVM_ATTRIBUTE_UNUSED_RESULT __attribute__((__warn_unused_result__))
|
||||
#else
|
||||
#define LLVM_ATTRIBUTE_UNUSED_RESULT
|
||||
#endif
|
||||
|
||||
// Some compilers warn about unused functions. When a function is sometimes
|
||||
// used or not depending on build settings (e.g. a function only called from
|
||||
// within "assert"), this attribute can be used to suppress such warnings.
|
||||
//
|
||||
// However, it shouldn't be used for unused *variables*, as those have a much
|
||||
// more portable solution:
|
||||
// (void)unused_var_name;
|
||||
// Prefer cast-to-void wherever it is sufficient.
|
||||
#if __has_attribute(unused) || LLVM_GNUC_PREREQ(3, 1, 0)
|
||||
#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
#define LLVM_ATTRIBUTE_UNUSED
|
||||
#endif
|
||||
|
||||
// FIXME: Provide this for PE/COFF targets.
|
||||
#if (__has_attribute(weak) || LLVM_GNUC_PREREQ(4, 0, 0)) && \
|
||||
(!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32))
|
||||
#define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__))
|
||||
#else
|
||||
#define LLVM_ATTRIBUTE_WEAK
|
||||
#endif
|
||||
|
||||
// Prior to clang 3.2, clang did not accept any spelling of
|
||||
// __has_attribute(const), so assume it is supported.
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
// aka 'CONST' but following LLVM Conventions.
|
||||
#define LLVM_READNONE __attribute__((__const__))
|
||||
#else
|
||||
#define LLVM_READNONE
|
||||
#endif
|
||||
|
||||
#if __has_attribute(pure) || defined(__GNUC__)
|
||||
// aka 'PURE' but following LLVM Conventions.
|
||||
#define LLVM_READONLY __attribute__((__pure__))
|
||||
#else
|
||||
#define LLVM_READONLY
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin_expect) || LLVM_GNUC_PREREQ(4, 0, 0)
|
||||
#define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true)
|
||||
#define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false)
|
||||
#else
|
||||
#define LLVM_LIKELY(EXPR) (EXPR)
|
||||
#define LLVM_UNLIKELY(EXPR) (EXPR)
|
||||
#endif
|
||||
|
||||
/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so,
|
||||
/// mark a method "not for inlining".
|
||||
#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0)
|
||||
#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline))
|
||||
#elif defined(_MSC_VER)
|
||||
#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline)
|
||||
#else
|
||||
#define LLVM_ATTRIBUTE_NOINLINE
|
||||
#endif
|
||||
|
||||
/// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do
|
||||
/// so, mark a method "always inline" because it is performance sensitive. GCC
|
||||
/// 3.4 supported this but is buggy in various cases and produces unimplemented
|
||||
/// errors, just use it in GCC 4.0 and later.
|
||||
#if __has_attribute(always_inline) || LLVM_GNUC_PREREQ(4, 0, 0)
|
||||
#define LLVM_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline))
|
||||
#elif defined(_MSC_VER)
|
||||
#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline
|
||||
#else
|
||||
#define LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn))
|
||||
#elif defined(_MSC_VER)
|
||||
#define LLVM_ATTRIBUTE_NORETURN __declspec(noreturn)
|
||||
#else
|
||||
#define LLVM_ATTRIBUTE_NORETURN
|
||||
#endif
|
||||
|
||||
#if __has_attribute(returns_nonnull) || LLVM_GNUC_PREREQ(4, 9, 0)
|
||||
#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))
|
||||
#else
|
||||
#define LLVM_ATTRIBUTE_RETURNS_NONNULL
|
||||
#endif
|
||||
|
||||
/// \macro LLVM_ATTRIBUTE_RETURNS_NOALIAS Used to mark a function as returning a
|
||||
/// pointer that does not alias any other valid pointer.
|
||||
#ifdef __GNUC__
|
||||
#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__))
|
||||
#elif defined(_MSC_VER)
|
||||
#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict)
|
||||
#else
|
||||
#define LLVM_ATTRIBUTE_RETURNS_NOALIAS
|
||||
#endif
|
||||
|
||||
/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress
|
||||
/// pedantic diagnostics.
|
||||
#ifdef __GNUC__
|
||||
#define LLVM_EXTENSION __extension__
|
||||
#else
|
||||
#define LLVM_EXTENSION
|
||||
#endif
|
||||
|
||||
// LLVM_ATTRIBUTE_DEPRECATED(decl, "message")
|
||||
#if __has_feature(attribute_deprecated_with_message)
|
||||
# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
|
||||
decl __attribute__((deprecated(message)))
|
||||
#elif defined(__GNUC__)
|
||||
# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
|
||||
decl __attribute__((deprecated))
|
||||
#elif defined(_MSC_VER)
|
||||
# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
|
||||
__declspec(deprecated(message)) decl
|
||||
#else
|
||||
# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
|
||||
decl
|
||||
#endif
|
||||
|
||||
/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands
|
||||
/// to an expression which states that it is undefined behavior for the
|
||||
/// compiler to reach this point. Otherwise is not defined.
|
||||
#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0)
|
||||
# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable()
|
||||
#elif defined(_MSC_VER)
|
||||
# define LLVM_BUILTIN_UNREACHABLE __assume(false)
|
||||
#endif
|
||||
|
||||
/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression
|
||||
/// which causes the program to exit abnormally.
|
||||
#if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0)
|
||||
# define LLVM_BUILTIN_TRAP __builtin_trap()
|
||||
#elif defined(_MSC_VER)
|
||||
// The __debugbreak intrinsic is supported by MSVC, does not require forward
|
||||
// declarations involving platform-specific typedefs (unlike RaiseException),
|
||||
// results in a call to vectored exception handlers, and encodes to a short
|
||||
// instruction that still causes the trapping behavior we want.
|
||||
# define LLVM_BUILTIN_TRAP __debugbreak()
|
||||
#else
|
||||
# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0
|
||||
#endif
|
||||
|
||||
/// \macro LLVM_ASSUME_ALIGNED
|
||||
/// \brief Returns a pointer with an assumed alignment.
|
||||
#if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0)
|
||||
# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a)
|
||||
#elif defined(LLVM_BUILTIN_UNREACHABLE)
|
||||
// As of today, clang does not support __builtin_assume_aligned.
|
||||
# define LLVM_ASSUME_ALIGNED(p, a) \
|
||||
(((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE, (p)))
|
||||
#else
|
||||
# define LLVM_ASSUME_ALIGNED(p, a) (p)
|
||||
#endif
|
||||
|
||||
/// \macro LLVM_ALIGNAS
|
||||
/// \brief Used to specify a minimum alignment for a structure or variable. The
|
||||
/// alignment must be a constant integer. Use LLVM_PTR_SIZE to compute
|
||||
/// alignments in terms of the size of a pointer.
|
||||
///
|
||||
/// Note that __declspec(align) has special quirks, it's not legal to pass a
|
||||
/// structure with __declspec(align) as a formal parameter.
|
||||
#ifdef _MSC_VER
|
||||
# define LLVM_ALIGNAS(x) __declspec(align(x))
|
||||
#elif __GNUC__ && !__has_feature(cxx_alignas) && !LLVM_GNUC_PREREQ(4, 8, 0)
|
||||
# define LLVM_ALIGNAS(x) __attribute__((aligned(x)))
|
||||
#else
|
||||
# define LLVM_ALIGNAS(x) alignas(x)
|
||||
#endif
|
||||
|
||||
/// \macro LLVM_PACKED
|
||||
/// \brief Used to specify a packed structure.
|
||||
/// LLVM_PACKED(
|
||||
/// struct A {
|
||||
/// int i;
|
||||
/// int j;
|
||||
/// int k;
|
||||
/// long long l;
|
||||
/// });
|
||||
///
|
||||
/// LLVM_PACKED_START
|
||||
/// struct B {
|
||||
/// int i;
|
||||
/// int j;
|
||||
/// int k;
|
||||
/// long long l;
|
||||
/// };
|
||||
/// LLVM_PACKED_END
|
||||
#ifdef _MSC_VER
|
||||
# define LLVM_PACKED(d) __pragma(pack(push, 1)) d __pragma(pack(pop))
|
||||
# define LLVM_PACKED_START __pragma(pack(push, 1))
|
||||
# define LLVM_PACKED_END __pragma(pack(pop))
|
||||
#else
|
||||
# define LLVM_PACKED(d) d __attribute__((packed))
|
||||
# define LLVM_PACKED_START _Pragma("pack(push, 1)")
|
||||
# define LLVM_PACKED_END _Pragma("pack(pop)")
|
||||
#endif
|
||||
|
||||
/// \macro LLVM_PTR_SIZE
|
||||
/// \brief A constant integer equivalent to the value of sizeof(void*).
|
||||
/// Generally used in combination with LLVM_ALIGNAS or when doing computation in
|
||||
/// the preprocessor.
|
||||
#ifdef __SIZEOF_POINTER__
|
||||
# define LLVM_PTR_SIZE __SIZEOF_POINTER__
|
||||
#elif defined(_WIN64)
|
||||
# define LLVM_PTR_SIZE 8
|
||||
#elif defined(_WIN32)
|
||||
# define LLVM_PTR_SIZE 4
|
||||
#elif defined(_MSC_VER)
|
||||
# error "could not determine LLVM_PTR_SIZE as a constant int for MSVC"
|
||||
#else
|
||||
# define LLVM_PTR_SIZE sizeof(void *)
|
||||
#endif
|
||||
|
||||
/// \macro LLVM_FUNCTION_NAME
|
||||
/// \brief Expands to __func__ on compilers which support it. Otherwise,
|
||||
/// expands to a compiler-dependent replacement.
|
||||
#if defined(_MSC_VER)
|
||||
# define LLVM_FUNCTION_NAME __FUNCTION__
|
||||
#else
|
||||
# define LLVM_FUNCTION_NAME __func__
|
||||
#endif
|
||||
|
||||
/// \macro LLVM_MEMORY_SANITIZER_BUILD
|
||||
/// \brief Whether LLVM itself is built with MemorySanitizer instrumentation.
|
||||
#if __has_feature(memory_sanitizer)
|
||||
# define LLVM_MEMORY_SANITIZER_BUILD 1
|
||||
# include <sanitizer/msan_interface.h>
|
||||
#else
|
||||
# define LLVM_MEMORY_SANITIZER_BUILD 0
|
||||
# define __msan_allocated_memory(p, size)
|
||||
# define __msan_unpoison(p, size)
|
||||
#endif
|
||||
|
||||
/// \macro LLVM_ADDRESS_SANITIZER_BUILD
|
||||
/// \brief Whether LLVM itself is built with AddressSanitizer instrumentation.
|
||||
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
# define LLVM_ADDRESS_SANITIZER_BUILD 1
|
||||
# include <sanitizer/asan_interface.h>
|
||||
#else
|
||||
# define LLVM_ADDRESS_SANITIZER_BUILD 0
|
||||
# define __asan_poison_memory_region(p, size)
|
||||
# define __asan_unpoison_memory_region(p, size)
|
||||
#endif
|
||||
|
||||
/// \macro LLVM_THREAD_SANITIZER_BUILD
|
||||
/// \brief Whether LLVM itself is built with ThreadSanitizer instrumentation.
|
||||
#if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)
|
||||
# define LLVM_THREAD_SANITIZER_BUILD 1
|
||||
#else
|
||||
# define LLVM_THREAD_SANITIZER_BUILD 0
|
||||
#endif
|
||||
|
||||
#if LLVM_THREAD_SANITIZER_BUILD
|
||||
// Thread Sanitizer is a tool that finds races in code.
|
||||
// See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations .
|
||||
// tsan detects these exact functions by name.
|
||||
extern "C" {
|
||||
void AnnotateHappensAfter(const char *file, int line, const volatile void *cv);
|
||||
void AnnotateHappensBefore(const char *file, int line, const volatile void *cv);
|
||||
void AnnotateIgnoreWritesBegin(const char *file, int line);
|
||||
void AnnotateIgnoreWritesEnd(const char *file, int line);
|
||||
}
|
||||
|
||||
// This marker is used to define a happens-before arc. The race detector will
|
||||
// infer an arc from the begin to the end when they share the same pointer
|
||||
// argument.
|
||||
# define TsanHappensBefore(cv) AnnotateHappensBefore(__FILE__, __LINE__, cv)
|
||||
|
||||
// This marker defines the destination of a happens-before arc.
|
||||
# define TsanHappensAfter(cv) AnnotateHappensAfter(__FILE__, __LINE__, cv)
|
||||
|
||||
// Ignore any races on writes between here and the next TsanIgnoreWritesEnd.
|
||||
# define TsanIgnoreWritesBegin() AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
|
||||
|
||||
// Resume checking for racy writes.
|
||||
# define TsanIgnoreWritesEnd() AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
|
||||
#else
|
||||
# define TsanHappensBefore(cv)
|
||||
# define TsanHappensAfter(cv)
|
||||
# define TsanIgnoreWritesBegin()
|
||||
# define TsanIgnoreWritesEnd()
|
||||
#endif
|
||||
|
||||
/// \brief Mark debug helper function definitions like dump() that should not be
|
||||
/// stripped from debug builds.
|
||||
// FIXME: Move this to a private config.h as it's not usable in public headers.
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||
#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED
|
||||
#else
|
||||
#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE
|
||||
#endif
|
||||
|
||||
/// \macro LLVM_THREAD_LOCAL
|
||||
/// \brief A thread-local storage specifier which can be used with globals,
|
||||
/// extern globals, and static globals.
|
||||
///
|
||||
/// This is essentially an extremely restricted analog to C++11's thread_local
|
||||
/// support, and uses that when available. However, it falls back on
|
||||
/// platform-specific or vendor-provided extensions when necessary. These
|
||||
/// extensions don't support many of the C++11 thread_local's features. You
|
||||
/// should only use this for PODs that you can statically initialize to
|
||||
/// some constant value. In almost all circumstances this is most appropriate
|
||||
/// for use with a pointer, integer, or small aggregation of pointers and
|
||||
/// integers.
|
||||
#if LLVM_ENABLE_THREADS
|
||||
#if __has_feature(cxx_thread_local)
|
||||
#define LLVM_THREAD_LOCAL thread_local
|
||||
#elif defined(_MSC_VER)
|
||||
// MSVC supports this with a __declspec.
|
||||
#define LLVM_THREAD_LOCAL __declspec(thread)
|
||||
#else
|
||||
// Clang, GCC, and other compatible compilers used __thread prior to C++11 and
|
||||
// we only need the restricted functionality that provides.
|
||||
#define LLVM_THREAD_LOCAL __thread
|
||||
#endif
|
||||
#else // !LLVM_ENABLE_THREADS
|
||||
// If threading is disabled entirely, this compiles to nothing and you get
|
||||
// a normal global variable.
|
||||
#define LLVM_THREAD_LOCAL
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,211 @@
|
||||
//
|
||||
// Container+DeepSearch
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-08-25.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/** Deep key search based methods for hierarchical container structures.
|
||||
*
|
||||
* A deep key search works like a normal search, except that the "key" is
|
||||
* interpreted as a series of keys, to be recursively applied in a "drill down"
|
||||
* fashion. There are two variants of each: the "deep key" variant, where the
|
||||
* key series is passed as an array, and the "key path" variant, where the
|
||||
* key series is passed as a serialized path, similar to filesystem paths
|
||||
* (a string where entries are separated by slashes).
|
||||
*
|
||||
* For example, if objectForDeepKey were called with [@"top", @"sublevel", @"2",
|
||||
* @"item] (or objectForKeyPath were called with @"top/sublevel/2/item"), it
|
||||
* would search as follows:
|
||||
*
|
||||
* result = [self objectForKey:@"top"];
|
||||
* result = [result objectForKey:@"sublevel"];
|
||||
* result = [result objectForKey:@"2"];
|
||||
* result = [result objectForKey:@"item"];
|
||||
*
|
||||
* Note that if any potential container along the way does not respond to
|
||||
* "objectForKey:", it will check to see if the container responds to
|
||||
* "objectAtIndex:" AND the current key responds to "intValue". If both do
|
||||
* respond, it will retrieve the current result using an array lookup:
|
||||
*
|
||||
* result = [result objectAtIndex:[currentKey intValue]];
|
||||
*/
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
#pragma mark - NSDictionary -
|
||||
|
||||
/**
|
||||
* Deep key search methods for NSDictionary.
|
||||
*/
|
||||
@interface NSDictionary (DeepSearch)
|
||||
|
||||
#pragma mark - Lookups
|
||||
|
||||
/** Do a deep search using the specified keys.
|
||||
*
|
||||
* A failed lookup returns nil, except in the case of a failed array-style
|
||||
* lookup, in which case it may throw an "index out of range" exception.
|
||||
*
|
||||
* @param deepKey A set of keys to drill down with.
|
||||
*/
|
||||
- (id) objectForDeepKey:(NSArray*) deepKey;
|
||||
|
||||
|
||||
/** Do a deep search using the specified keys.
|
||||
*
|
||||
* A failed lookup returns nil, except in the case of a failed array-style
|
||||
* lookup, in which case it may throw an "index out of range" exception.
|
||||
*
|
||||
* @param keyPath A full key path, separated by slash (e.g. @"a/b/c")
|
||||
*/
|
||||
- (id) objectForKeyPath:(NSString*) keyPath;
|
||||
|
||||
|
||||
#pragma mark - Mutators
|
||||
|
||||
/** Set an associated object at the specified deep key.
|
||||
*
|
||||
* The object will be stored either dictionary style "setObject:forKey:" or
|
||||
* array style "replaceObjectAtIndex:withObject:", depending on what the
|
||||
* final container object responds to.
|
||||
*
|
||||
* If the lookup fails at any level, it will throw an exception describing which
|
||||
* object in the hierarchy did not respond to any object accessor methods.
|
||||
*/
|
||||
- (void) setObject:(id) anObject forDeepKey:(NSArray*) deepKey;
|
||||
|
||||
/** Set an associated object at the specified key path.
|
||||
*
|
||||
* The object will be stored either dictionary style "setObject:forKey:" or
|
||||
* array style "replaceObjectAtIndex:withObject:", depending on what the
|
||||
* final container object responds to.
|
||||
*
|
||||
* If the lookup fails at any level, it will throw an exception describing which
|
||||
* object in the hierarchy did not respond to any object accessor methods.
|
||||
*/
|
||||
- (void) setObject:(id) anObject forKeyPath:(NSString*) keyPath;
|
||||
|
||||
/** Remove an associated object at the specified deep key.
|
||||
*
|
||||
* The object will be stored either dictionary style "removeObjectForKey:" or
|
||||
* array style "removeObjectAtIndex:", depending on what the final container
|
||||
* object responds to.
|
||||
*
|
||||
* If the lookup fails at any level, it will throw an exception describing which
|
||||
* object in the hierarchy did not respond to any object accessor methods.
|
||||
*/
|
||||
- (void) removeObjectForDeepKey:(NSArray*) deepKey;
|
||||
|
||||
/** Remove an associated object at the specified key path.
|
||||
*
|
||||
* The object will be stored either dictionary style "removeObjectForKey:" or
|
||||
* array style "removeObjectAtIndex:", depending on what the final container
|
||||
* object responds to.
|
||||
*
|
||||
* If the lookup fails at any level, it will throw an exception describing which
|
||||
* object in the hierarchy did not respond to any object accessor methods.
|
||||
*/
|
||||
- (void) removeObjectForKeyPath:(NSString*) keyPath;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark - NSArray -
|
||||
|
||||
/**
|
||||
* Deep key search methods for NSDictionary.
|
||||
*/
|
||||
@interface NSArray (DeepSearch)
|
||||
|
||||
#pragma mark - Lookups
|
||||
|
||||
/** Do a deep search using the specified keys.
|
||||
*
|
||||
* A failed lookup returns nil, except in the case of a failed array-style
|
||||
* lookup, in which case it may throw an "index out of range" exception.
|
||||
*
|
||||
* @param deepKey A set of keys to drill down with.
|
||||
*/
|
||||
- (id) objectForDeepKey:(NSArray*) deepKey;
|
||||
|
||||
|
||||
/** Do a deep search using the specified keys.
|
||||
*
|
||||
* A failed lookup returns nil, except in the case of a failed array-style
|
||||
* lookup, in which case it may throw an "index out of range" exception.
|
||||
*
|
||||
* @param keyPath A full key path, separated by slash (e.g. @"a/b/c")
|
||||
*/
|
||||
- (id) objectForKeyPath:(NSString*) keyPath;
|
||||
|
||||
|
||||
#pragma mark - Mutators
|
||||
|
||||
/** Set an associated object at the specified deep key.
|
||||
*
|
||||
* The object will be stored either dictionary style "setObject:forKey:" or
|
||||
* array style "replaceObjectAtIndex:withObject:", depending on what the
|
||||
* final container object responds to.
|
||||
*
|
||||
* If the lookup fails at any level, it will throw an exception describing which
|
||||
* object in the hierarchy did not respond to any object accessor methods.
|
||||
*/
|
||||
- (void) setObject:(id) anObject forDeepKey:(NSArray*) deepKey;
|
||||
|
||||
/** Set an associated object at the specified key path.
|
||||
*
|
||||
* The object will be stored either dictionary style "setObject:forKey:" or
|
||||
* array style "replaceObjectAtIndex:withObject:", depending on what the
|
||||
* final container object responds to.
|
||||
*
|
||||
* If the lookup fails at any level, it will throw an exception describing which
|
||||
* object in the hierarchy did not respond to any object accessor methods.
|
||||
*/
|
||||
- (void) setObject:(id) anObject forKeyPath:(NSString*) keyPath;
|
||||
|
||||
/** Remove an associated object at the specified deep key.
|
||||
*
|
||||
* The object will be stored either dictionary style "removeObjectForKey:" or
|
||||
* array style "removeObjectAtIndex:", depending on what the final container
|
||||
* object responds to.
|
||||
*
|
||||
* If the lookup fails at any level, it will throw an exception describing which
|
||||
* object in the hierarchy did not respond to any object accessor methods.
|
||||
*/
|
||||
- (void) removeObjectForDeepKey:(NSArray*) deepKey;
|
||||
|
||||
/** Remove an associated object at the specified key path.
|
||||
*
|
||||
* The object will be stored either dictionary style "removeObjectForKey:" or
|
||||
* array style "removeObjectAtIndex:", depending on what the final container
|
||||
* object responds to.
|
||||
*
|
||||
* If the lookup fails at any level, it will throw an exception describing which
|
||||
* object in the hierarchy did not respond to any object accessor methods.
|
||||
*/
|
||||
- (void) removeObjectForKeyPath:(NSString*) keyPath;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,608 @@
|
||||
//===--- Demangle.h - Interface to Swift symbol demangling ------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is the public API of the demangler library.
|
||||
// Tools which use the demangler library (like lldb) must include this - and
|
||||
// only this - header file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_DEMANGLING_DEMANGLE_H
|
||||
#define SWIFT_DEMANGLING_DEMANGLE_H
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include "StringRef.h"
|
||||
#include "Config.h"
|
||||
|
||||
namespace llvm {
|
||||
class raw_ostream;
|
||||
}
|
||||
|
||||
namespace swift {
|
||||
namespace Demangle {
|
||||
|
||||
enum class SymbolicReferenceKind : uint8_t;
|
||||
|
||||
struct DemangleOptions {
|
||||
bool SynthesizeSugarOnTypes = false;
|
||||
bool DisplayDebuggerGeneratedModule = true;
|
||||
bool QualifyEntities = true;
|
||||
bool DisplayExtensionContexts = true;
|
||||
bool DisplayUnmangledSuffix = true;
|
||||
bool DisplayModuleNames = true;
|
||||
bool DisplayGenericSpecializations = true;
|
||||
bool DisplayProtocolConformances = true;
|
||||
bool DisplayWhereClauses = true;
|
||||
bool DisplayEntityTypes = true;
|
||||
bool ShortenPartialApply = false;
|
||||
bool ShortenThunk = false;
|
||||
bool ShortenValueWitness = false;
|
||||
bool ShortenArchetype = false;
|
||||
bool ShowPrivateDiscriminators = true;
|
||||
bool ShowFunctionArgumentTypes = true;
|
||||
|
||||
DemangleOptions() {}
|
||||
|
||||
static DemangleOptions SimplifiedUIDemangleOptions() {
|
||||
auto Opt = DemangleOptions();
|
||||
Opt.SynthesizeSugarOnTypes = true;
|
||||
Opt.QualifyEntities = true;
|
||||
Opt.DisplayExtensionContexts = false;
|
||||
Opt.DisplayUnmangledSuffix = false;
|
||||
Opt.DisplayModuleNames = false;
|
||||
Opt.DisplayGenericSpecializations = false;
|
||||
Opt.DisplayProtocolConformances = false;
|
||||
Opt.DisplayWhereClauses = false;
|
||||
Opt.DisplayEntityTypes = false;
|
||||
Opt.ShortenPartialApply = true;
|
||||
Opt.ShortenThunk = true;
|
||||
Opt.ShortenValueWitness = true;
|
||||
Opt.ShortenArchetype = true;
|
||||
Opt.ShowPrivateDiscriminators = false;
|
||||
Opt.ShowFunctionArgumentTypes = false;
|
||||
return Opt;
|
||||
};
|
||||
};
|
||||
|
||||
class Node;
|
||||
using NodePointer = Node *;
|
||||
|
||||
enum class FunctionSigSpecializationParamKind : unsigned {
|
||||
// Option Flags use bits 0-5. This give us 6 bits implying 64 entries to
|
||||
// work with.
|
||||
ConstantPropFunction = 0,
|
||||
ConstantPropGlobal = 1,
|
||||
ConstantPropInteger = 2,
|
||||
ConstantPropFloat = 3,
|
||||
ConstantPropString = 4,
|
||||
ClosureProp = 5,
|
||||
BoxToValue = 6,
|
||||
BoxToStack = 7,
|
||||
|
||||
// Option Set Flags use bits 6-31. This gives us 26 bits to use for option
|
||||
// flags.
|
||||
Dead = 1 << 6,
|
||||
OwnedToGuaranteed = 1 << 7,
|
||||
SROA = 1 << 8,
|
||||
GuaranteedToOwned = 1 << 9,
|
||||
ExistentialToGeneric = 1 << 10,
|
||||
};
|
||||
|
||||
/// The pass that caused the specialization to occur. We use this to make sure
|
||||
/// that two passes that generate similar changes do not yield the same
|
||||
/// mangling. This currently cannot happen, so this is just a safety measure
|
||||
/// that creates separate name spaces.
|
||||
enum class SpecializationPass : uint8_t {
|
||||
AllocBoxToStack,
|
||||
ClosureSpecializer,
|
||||
CapturePromotion,
|
||||
CapturePropagation,
|
||||
FunctionSignatureOpts,
|
||||
GenericSpecializer,
|
||||
};
|
||||
|
||||
static inline char encodeSpecializationPass(SpecializationPass Pass) {
|
||||
return char(uint8_t(Pass)) + '0';
|
||||
}
|
||||
|
||||
enum class ValueWitnessKind {
|
||||
#define VALUE_WITNESS(MANGLING, NAME) \
|
||||
NAME,
|
||||
#include "ValueWitnessMangling.def"
|
||||
};
|
||||
|
||||
enum class Directness {
|
||||
Direct, Indirect
|
||||
};
|
||||
|
||||
class NodeFactory;
|
||||
class Context;
|
||||
|
||||
class Node {
|
||||
public:
|
||||
enum class Kind : uint16_t {
|
||||
#define NODE(ID) ID,
|
||||
#include "DemangleNodes.def"
|
||||
};
|
||||
|
||||
using IndexType = uint64_t;
|
||||
|
||||
friend class NodeFactory;
|
||||
|
||||
private:
|
||||
Kind NodeKind;
|
||||
|
||||
enum class PayloadKind : uint8_t {
|
||||
None, Text, Index
|
||||
};
|
||||
PayloadKind NodePayloadKind;
|
||||
|
||||
union {
|
||||
llvm::StringRef TextPayload;
|
||||
IndexType IndexPayload;
|
||||
};
|
||||
|
||||
NodePointer *Children = nullptr;
|
||||
size_t NumChildren = 0;
|
||||
size_t ReservedChildren = 0;
|
||||
|
||||
Node(Kind k)
|
||||
: NodeKind(k), NodePayloadKind(PayloadKind::None) {
|
||||
}
|
||||
Node(Kind k, llvm::StringRef t)
|
||||
: NodeKind(k), NodePayloadKind(PayloadKind::Text) {
|
||||
TextPayload = t;
|
||||
}
|
||||
Node(Kind k, IndexType index)
|
||||
: NodeKind(k), NodePayloadKind(PayloadKind::Index) {
|
||||
IndexPayload = index;
|
||||
}
|
||||
Node(const Node &) = delete;
|
||||
Node &operator=(const Node &) = delete;
|
||||
|
||||
public:
|
||||
Kind getKind() const { return NodeKind; }
|
||||
|
||||
bool hasText() const { return NodePayloadKind == PayloadKind::Text; }
|
||||
llvm::StringRef getText() const {
|
||||
assert(hasText());
|
||||
return TextPayload;
|
||||
}
|
||||
|
||||
bool hasIndex() const { return NodePayloadKind == PayloadKind::Index; }
|
||||
uint64_t getIndex() const {
|
||||
assert(hasIndex());
|
||||
return IndexPayload;
|
||||
}
|
||||
|
||||
using iterator = NodePointer *;
|
||||
using const_iterator = const NodePointer *;
|
||||
using size_type = size_t;
|
||||
|
||||
bool hasChildren() const { return NumChildren != 0; }
|
||||
size_t getNumChildren() const { return NumChildren; }
|
||||
iterator begin() { return Children; }
|
||||
iterator end() { return Children + NumChildren; }
|
||||
const_iterator begin() const { return Children; }
|
||||
const_iterator end() const { return Children + NumChildren; }
|
||||
|
||||
NodePointer getFirstChild() const {
|
||||
assert(NumChildren >= 1);
|
||||
return Children[0];
|
||||
}
|
||||
NodePointer getChild(size_t index) const {
|
||||
assert(NumChildren > index);
|
||||
return Children[index];
|
||||
}
|
||||
|
||||
// inline void addChild(NodePointer Child, Context &Ctx);
|
||||
|
||||
// Only to be used by the demangler parsers.
|
||||
void addChild(NodePointer Child, NodeFactory &Factory);
|
||||
// Only to be used by the demangler parsers.
|
||||
void removeChildAt(unsigned Pos, NodeFactory &factory);
|
||||
|
||||
// Reverses the order of children.
|
||||
void reverseChildren(size_t StartingAt = 0);
|
||||
|
||||
/// Prints the whole node tree in readable form to stderr.
|
||||
///
|
||||
/// Useful to be called from the debugger.
|
||||
void dump();
|
||||
};
|
||||
|
||||
/// Returns the length of the swift mangling prefix of the \p SymbolName.
|
||||
///
|
||||
/// Returns 0 if \p SymbolName is not a mangled swift (>= swift 4.x) name.
|
||||
int getManglingPrefixLength(llvm::StringRef mangledName);
|
||||
|
||||
/// Returns true if \p SymbolName is a mangled swift name.
|
||||
///
|
||||
/// This does not include the old (<= swift 3.x) mangling prefix "_T".
|
||||
inline bool isMangledName(llvm::StringRef mangledName) {
|
||||
return getManglingPrefixLength(mangledName) != 0;
|
||||
}
|
||||
|
||||
/// Returns true if the mangledName starts with the swift mangling prefix.
|
||||
///
|
||||
/// This includes the old (<= swift 3.x) mangling prefix "_T".
|
||||
bool isSwiftSymbol(llvm::StringRef mangledName);
|
||||
|
||||
/// Returns true if the mangledName starts with the swift mangling prefix.
|
||||
///
|
||||
/// This includes the old (<= swift 3.x) mangling prefix "_T".
|
||||
bool isSwiftSymbol(const char *mangledName);
|
||||
|
||||
/// Drops the Swift mangling prefix from the given mangled name, if there is
|
||||
/// one.
|
||||
///
|
||||
/// This does not include the old (<= swift 3.x) mangling prefix "_T".
|
||||
llvm::StringRef dropSwiftManglingPrefix(llvm::StringRef mangledName);
|
||||
|
||||
/// Returns true if the mangled name is an alias type name.
|
||||
///
|
||||
/// \param mangledName A null-terminated string containing a mangled name.
|
||||
bool isAlias(llvm::StringRef mangledName);
|
||||
|
||||
/// Returns true if the mangled name is a class type name.
|
||||
///
|
||||
/// \param mangledName A null-terminated string containing a mangled name.
|
||||
bool isClass(llvm::StringRef mangledName);
|
||||
|
||||
/// Returns true if the mangled name is an enum type name.
|
||||
///
|
||||
/// \param mangledName A null-terminated string containing a mangled name.
|
||||
bool isEnum(llvm::StringRef mangledName);
|
||||
|
||||
/// Returns true if the mangled name is a protocol type name.
|
||||
///
|
||||
/// \param mangledName A null-terminated string containing a mangled name.
|
||||
bool isProtocol(llvm::StringRef mangledName);
|
||||
|
||||
/// Returns true if the mangled name is a structure type name.
|
||||
///
|
||||
/// \param mangledName A null-terminated string containing a mangled name.
|
||||
bool isStruct(llvm::StringRef mangledName);
|
||||
|
||||
/// Returns true if the mangled name is an Objective-C symbol.
|
||||
///
|
||||
/// \param mangledName A null-terminated string containing a mangled name.
|
||||
bool isObjCSymbol(llvm::StringRef mangledName);
|
||||
|
||||
/// Returns true if the mangled name has the old scheme of function type
|
||||
/// mangling where labels are part of the type.
|
||||
///
|
||||
/// \param mangledName A null-terminated string containing a mangled name.
|
||||
bool isOldFunctionTypeMangling(llvm::StringRef mangledName);
|
||||
|
||||
class Demangler;
|
||||
|
||||
/// The demangler context.
|
||||
///
|
||||
/// It owns the allocated nodes which are created during demangling.
|
||||
/// It is always preferable to use the demangling via this context class as it
|
||||
/// ensures efficient memory management. Especially if demangling is done for
|
||||
/// multiple symbols. Typical usage:
|
||||
/// \code
|
||||
/// Context Ctx;
|
||||
/// for (...) {
|
||||
/// NodePointer Root = Ctx.demangleSymbolAsNode(MangledName);
|
||||
/// // Do something with Root
|
||||
/// Ctx.clear(); // deallocates Root
|
||||
/// }
|
||||
/// \endcode
|
||||
/// Declaring the context out of the loop minimizes the amount of needed memory
|
||||
/// allocations.
|
||||
///
|
||||
class Context {
|
||||
Demangler *D;
|
||||
|
||||
friend class Node;
|
||||
|
||||
public:
|
||||
Context();
|
||||
|
||||
~Context();
|
||||
|
||||
/// Demangle the given symbol and return the parse tree.
|
||||
///
|
||||
/// \param MangledName The mangled symbol string, which start a mangling
|
||||
/// prefix: _T, _T0, $S, _$S.
|
||||
///
|
||||
/// \returns A parse tree for the demangled string - or a null pointer
|
||||
/// on failure.
|
||||
/// The lifetime of the returned node tree ends with the lifetime of the
|
||||
/// context or with a call of clear().
|
||||
NodePointer demangleSymbolAsNode(llvm::StringRef MangledName);
|
||||
|
||||
/// Demangle the given type and return the parse tree.
|
||||
///
|
||||
/// \param MangledName The mangled symbol string, which start a mangling
|
||||
/// prefix: _T, _T0, $S, _$S.
|
||||
///
|
||||
/// \returns A parse tree for the demangled string - or a null pointer
|
||||
/// on failure.
|
||||
/// The lifetime of the returned node tree ends with the lifetime of the
|
||||
/// context or with a call of clear().
|
||||
NodePointer demangleTypeAsNode(llvm::StringRef MangledName);
|
||||
|
||||
/// Demangle the given symbol and return the readable name.
|
||||
///
|
||||
/// \param MangledName The mangled symbol string, which start a mangling
|
||||
/// prefix: _T, _T0, $S, _$S.
|
||||
///
|
||||
/// \returns The demangled string.
|
||||
std::string demangleSymbolAsString(llvm::StringRef MangledName,
|
||||
const DemangleOptions &Options = DemangleOptions());
|
||||
|
||||
/// Demangle the given type and return the readable name.
|
||||
///
|
||||
/// \param MangledName The mangled type string, which does _not_ start with
|
||||
/// a mangling prefix.
|
||||
///
|
||||
/// \returns The demangled string.
|
||||
std::string demangleTypeAsString(llvm::StringRef MangledName,
|
||||
const DemangleOptions &Options = DemangleOptions());
|
||||
|
||||
/// Returns true if the mangledName refers to a thunk function.
|
||||
///
|
||||
/// Thunk functions are either (ObjC) partial apply forwarder, swift-as-ObjC
|
||||
/// or ObjC-as-swift thunks or allocating init functions.
|
||||
bool isThunkSymbol(llvm::StringRef MangledName);
|
||||
|
||||
/// Returns the mangled name of the target of a thunk.
|
||||
///
|
||||
/// \returns Returns the remaining name after removing the thunk mangling
|
||||
/// characters from \p MangledName. If \p MangledName is not a thunk symbol
|
||||
/// or the thunk target cannot be derived from the mangling, an empty string
|
||||
/// is returned.
|
||||
std::string getThunkTarget(llvm::StringRef MangledName);
|
||||
|
||||
/// Returns true if the \p mangledName refers to a function which conforms to
|
||||
/// the Swift calling convention.
|
||||
///
|
||||
/// The return value is unspecified if the \p MangledName does not refer to a
|
||||
/// function symbol.
|
||||
bool hasSwiftCallingConvention(llvm::StringRef MangledName);
|
||||
|
||||
/// Deallocates all nodes.
|
||||
///
|
||||
/// The memory which is used for nodes is not freed but recycled for the next
|
||||
/// demangling operation.
|
||||
void clear();
|
||||
};
|
||||
|
||||
/// Standalone utility function to demangle the given symbol as string.
|
||||
///
|
||||
/// If performance is an issue when demangling multiple symbols,
|
||||
/// Context::demangleSymbolAsString should be used instead.
|
||||
/// \param mangledName The mangled name string pointer.
|
||||
/// \param mangledNameLength The length of the mangledName string.
|
||||
/// \returns The demangled string.
|
||||
std::string
|
||||
demangleSymbolAsString(const char *mangledName, size_t mangledNameLength,
|
||||
const DemangleOptions &options = DemangleOptions());
|
||||
|
||||
/// Standalone utility function to demangle the given symbol as string.
|
||||
///
|
||||
/// If performance is an issue when demangling multiple symbols,
|
||||
/// Context::demangleSymbolAsString should be used instead.
|
||||
/// \param mangledName The mangled name string.
|
||||
/// \returns The demangled string.
|
||||
inline std::string
|
||||
demangleSymbolAsString(const std::string &mangledName,
|
||||
const DemangleOptions &options = DemangleOptions()) {
|
||||
return demangleSymbolAsString(mangledName.data(), mangledName.size(),
|
||||
options);
|
||||
}
|
||||
|
||||
/// Standalone utility function to demangle the given symbol as string.
|
||||
///
|
||||
/// If performance is an issue when demangling multiple symbols,
|
||||
/// Context::demangleSymbolAsString should be used instead.
|
||||
/// \param MangledName The mangled name string.
|
||||
/// \returns The demangled string.
|
||||
// inline std::string
|
||||
// demangleSymbolAsString(llvm::StringRef MangledName,
|
||||
// const DemangleOptions &Options = DemangleOptions()) {
|
||||
// return demangleSymbolAsString(MangledName.data(),
|
||||
// MangledName.size(), Options);
|
||||
// }
|
||||
|
||||
/// Standalone utility function to demangle the given type as string.
|
||||
///
|
||||
/// If performance is an issue when demangling multiple symbols,
|
||||
/// Context::demangleTypeAsString should be used instead.
|
||||
/// \param mangledName The mangled name string pointer.
|
||||
/// \param mangledNameLength The length of the mangledName string.
|
||||
/// \returns The demangled string.
|
||||
std::string
|
||||
demangleTypeAsString(const char *mangledName, size_t mangledNameLength,
|
||||
const DemangleOptions &options = DemangleOptions());
|
||||
|
||||
/// Standalone utility function to demangle the given type as string.
|
||||
///
|
||||
/// If performance is an issue when demangling multiple symbols,
|
||||
/// Context::demangleTypeAsString should be used instead.
|
||||
/// \param mangledName The mangled name string.
|
||||
/// \returns The demangled string.
|
||||
inline std::string
|
||||
demangleTypeAsString(const std::string &mangledName,
|
||||
const DemangleOptions &options = DemangleOptions()) {
|
||||
return demangleTypeAsString(mangledName.data(), mangledName.size(), options);
|
||||
}
|
||||
|
||||
/// Standalone utility function to demangle the given type as string.
|
||||
///
|
||||
/// If performance is an issue when demangling multiple symbols,
|
||||
/// Context::demangleTypeAsString should be used instead.
|
||||
/// \param MangledName The mangled name string.
|
||||
/// \returns The demangled string.
|
||||
inline std::string
|
||||
demangleTypeAsString(llvm::StringRef MangledName,
|
||||
const DemangleOptions &Options = DemangleOptions()) {
|
||||
return demangleTypeAsString(MangledName.data(),
|
||||
MangledName.size(), Options);
|
||||
}
|
||||
|
||||
|
||||
enum class OperatorKind {
|
||||
NotOperator,
|
||||
Prefix,
|
||||
Postfix,
|
||||
Infix,
|
||||
};
|
||||
|
||||
/// Mangle an identifier using Swift's mangling rules.
|
||||
void mangleIdentifier(const char *data, size_t length,
|
||||
OperatorKind operatorKind, std::string &out,
|
||||
bool usePunycode = true);
|
||||
|
||||
// /// Remangle a demangled parse tree.
|
||||
// ///
|
||||
// /// This should always round-trip perfectly with demangleSymbolAsNode.
|
||||
// std::string mangleNode(NodePointer root);
|
||||
//
|
||||
// using SymbolicResolver =
|
||||
// llvm::function_ref<Demangle::NodePointer (SymbolicReferenceKind,
|
||||
// const void *)>;
|
||||
//
|
||||
// /// Remangle a demangled parse tree, using a callback to resolve
|
||||
// /// symbolic references.
|
||||
// ///
|
||||
// /// This should always round-trip perfectly with demangleSymbolAsNode.
|
||||
// std::string mangleNode(NodePointer root, SymbolicResolver resolver);
|
||||
//
|
||||
// /// Remangle in the old mangling scheme.
|
||||
// ///
|
||||
// /// This is only used for objc-runtime names and should be removed as soon as
|
||||
// /// we switch to the new mangling for those names as well.
|
||||
// std::string mangleNodeOld(NodePointer root);
|
||||
//
|
||||
/// Transform the node structure to a string.
|
||||
///
|
||||
/// Typical usage:
|
||||
/// \code
|
||||
/// std::string aDemangledName =
|
||||
/// swift::Demangler::nodeToString(aNode)
|
||||
/// \endcode
|
||||
///
|
||||
/// \param Root A pointer to a parse tree generated by the demangler.
|
||||
/// \param Options An object encapsulating options to use to perform this demangling.
|
||||
///
|
||||
/// \returns A string representing the demangled name.
|
||||
///
|
||||
std::string nodeToString(NodePointer Root,
|
||||
const DemangleOptions &Options = DemangleOptions());
|
||||
|
||||
/// A class for printing to a std::string.
|
||||
class DemanglerPrinter {
|
||||
public:
|
||||
DemanglerPrinter() = default;
|
||||
|
||||
DemanglerPrinter &operator<<(llvm::StringRef Value) & {
|
||||
Stream.append(Value.data(), Value.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
DemanglerPrinter &operator<<(char c) & {
|
||||
Stream.push_back(c);
|
||||
return *this;
|
||||
}
|
||||
DemanglerPrinter &operator<<(unsigned long long n) &;
|
||||
DemanglerPrinter &operator<<(long long n) &;
|
||||
DemanglerPrinter &operator<<(unsigned long n) & {
|
||||
return *this << (unsigned long long)n;
|
||||
}
|
||||
DemanglerPrinter &operator<<(long n) & {
|
||||
return *this << (long long)n;
|
||||
}
|
||||
DemanglerPrinter &operator<<(unsigned n) & {
|
||||
return *this << (unsigned long long)n;
|
||||
}
|
||||
DemanglerPrinter &operator<<(int n) & {
|
||||
return *this << (long long)n;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
DemanglerPrinter &&operator<<(T &&x) && {
|
||||
return std::move(*this << std::forward<T>(x));
|
||||
}
|
||||
|
||||
DemanglerPrinter &writeHex(unsigned long long n) &;
|
||||
|
||||
std::string &&str() && { return std::move(Stream); }
|
||||
|
||||
llvm::StringRef getStringRef() const { return Stream; }
|
||||
|
||||
/// Shrinks the buffer.
|
||||
void resetSize(size_t toPos) {
|
||||
assert(toPos <= Stream.size());
|
||||
Stream.resize(toPos);
|
||||
}
|
||||
private:
|
||||
std::string Stream;
|
||||
};
|
||||
|
||||
/// Returns a the node kind \p k as string.
|
||||
const char *getNodeKindString(swift::Demangle::Node::Kind k);
|
||||
|
||||
/// Prints the whole node tree \p Root in readable form into a std::string.
|
||||
///
|
||||
/// Useful for debugging.
|
||||
std::string getNodeTreeAsString(NodePointer Root);
|
||||
|
||||
bool nodeConsumesGenericArgs(Node *node);
|
||||
|
||||
bool isSpecialized(Node *node);
|
||||
|
||||
NodePointer getUnspecialized(Node *node, NodeFactory &Factory);
|
||||
std::string archetypeName(Node::IndexType index, Node::IndexType depth);
|
||||
|
||||
/// Form a StringRef around the mangled name starting at base, if the name may
|
||||
/// contain symbolic references.
|
||||
llvm::StringRef makeSymbolicMangledNameStringRef(const char *base);
|
||||
|
||||
} // end namespace Demangle
|
||||
} // end namespace swift
|
||||
|
||||
// NB: This function is not used directly in the Swift codebase, but is
|
||||
// exported for Xcode support and is used by the sanitizers. Please coordinate
|
||||
// before changing.
|
||||
//
|
||||
/// Demangles a Swift symbol name.
|
||||
///
|
||||
/// \param mangledName is the symbol name that needs to be demangled.
|
||||
/// \param mangledNameLength is the length of the string that should be
|
||||
/// demangled.
|
||||
/// \param outputBuffer is the user provided buffer where the demangled name
|
||||
/// will be placed. If nullptr, a new buffer will be malloced. In that case,
|
||||
/// the user of this API is responsible for freeing the returned buffer.
|
||||
/// \param outputBufferSize is the size of the output buffer. If the demangled
|
||||
/// name does not fit into the outputBuffer, the output will be truncated and
|
||||
/// the size will be updated, indicating how large the buffer should be.
|
||||
/// \param flags can be used to select the demangling style. TODO: We should
|
||||
//// define what these will be.
|
||||
/// \returns the demangled name. Returns nullptr if the input String is not a
|
||||
/// Swift mangled name.
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
char *swift_demangle(const char *mangledName,
|
||||
size_t mangledNameLength,
|
||||
char *outputBuffer,
|
||||
size_t *outputBufferSize,
|
||||
uint32_t flags);
|
||||
|
||||
#endif // SWIFT_DEMANGLING_DEMANGLE_H
|
||||
@@ -0,0 +1,168 @@
|
||||
//===--- DemangleNodes.def - Demangling Tree Metaprogramming ----*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines macros useful for macro-metaprogramming with nodes in
|
||||
// the demangling tree.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// NODE(ID)
|
||||
/// The node's enumerator value is Node::Kind::ID.
|
||||
|
||||
/// CONTEXT_NODE(ID)
|
||||
/// Nodes that can serve as contexts for other entities.
|
||||
#ifndef CONTEXT_NODE
|
||||
#define CONTEXT_NODE(ID) NODE(ID)
|
||||
#endif
|
||||
|
||||
CONTEXT_NODE(Allocator)
|
||||
NODE(Archetype)
|
||||
NODE(ArchetypeRef)
|
||||
NODE(ArgumentTuple)
|
||||
NODE(AssociatedType)
|
||||
NODE(AssociatedTypeRef)
|
||||
NODE(AssociatedTypeMetadataAccessor)
|
||||
NODE(AssociatedTypeWitnessTableAccessor)
|
||||
NODE(AutoClosureType)
|
||||
NODE(BoundGenericClass)
|
||||
NODE(BoundGenericEnum)
|
||||
NODE(BoundGenericStructure)
|
||||
NODE(BuiltinTypeName)
|
||||
NODE(CFunctionPointer)
|
||||
CONTEXT_NODE(Class)
|
||||
CONTEXT_NODE(Constructor)
|
||||
CONTEXT_NODE(Deallocator)
|
||||
NODE(DeclContext)
|
||||
CONTEXT_NODE(DefaultArgumentInitializer)
|
||||
NODE(DependentAssociatedTypeRef)
|
||||
NODE(DependentGenericConformanceRequirement)
|
||||
NODE(DependentGenericParamCount)
|
||||
NODE(DependentGenericParamType)
|
||||
NODE(DependentGenericSameTypeRequirement)
|
||||
NODE(DependentGenericSignature)
|
||||
NODE(DependentGenericType)
|
||||
NODE(DependentMemberType)
|
||||
NODE(DependentPseudogenericSignature)
|
||||
CONTEXT_NODE(Destructor)
|
||||
CONTEXT_NODE(DidSet)
|
||||
NODE(Directness)
|
||||
NODE(DynamicAttribute)
|
||||
NODE(DirectMethodReferenceAttribute)
|
||||
NODE(DynamicSelf)
|
||||
CONTEXT_NODE(Enum)
|
||||
NODE(ErrorType)
|
||||
NODE(ExistentialMetatype)
|
||||
CONTEXT_NODE(ExplicitClosure)
|
||||
CONTEXT_NODE(Extension)
|
||||
NODE(FieldOffset)
|
||||
NODE(FullTypeMetadata)
|
||||
CONTEXT_NODE(Function)
|
||||
NODE(FunctionSignatureSpecialization)
|
||||
NODE(FunctionSignatureSpecializationParam)
|
||||
NODE(FunctionSignatureSpecializationParamKind)
|
||||
NODE(FunctionSignatureSpecializationParamPayload)
|
||||
NODE(FunctionType)
|
||||
NODE(GenericProtocolWitnessTable)
|
||||
NODE(GenericProtocolWitnessTableInstantiationFunction)
|
||||
NODE(GenericSpecialization)
|
||||
NODE(GenericSpecializationNotReAbstracted)
|
||||
NODE(GenericSpecializationParam)
|
||||
NODE(GenericTypeMetadataPattern)
|
||||
CONTEXT_NODE(Getter)
|
||||
NODE(Global)
|
||||
CONTEXT_NODE(GlobalGetter)
|
||||
NODE(Identifier)
|
||||
NODE(Index)
|
||||
CONTEXT_NODE(IVarInitializer)
|
||||
CONTEXT_NODE(IVarDestroyer)
|
||||
NODE(ImplConvention)
|
||||
NODE(ImplFunctionAttribute)
|
||||
NODE(ImplFunctionType)
|
||||
CONTEXT_NODE(ImplicitClosure)
|
||||
NODE(ImplParameter)
|
||||
NODE(ImplResult)
|
||||
NODE(ImplErrorResult)
|
||||
NODE(InOut)
|
||||
NODE(InfixOperator)
|
||||
CONTEXT_NODE(Initializer)
|
||||
NODE(LazyProtocolWitnessTableAccessor)
|
||||
NODE(LazyProtocolWitnessTableCacheVariable)
|
||||
NODE(LocalDeclName)
|
||||
CONTEXT_NODE(MaterializeForSet)
|
||||
NODE(Metatype)
|
||||
NODE(MetatypeRepresentation)
|
||||
NODE(Metaclass)
|
||||
CONTEXT_NODE(Module)
|
||||
CONTEXT_NODE(NativeOwningAddressor)
|
||||
CONTEXT_NODE(NativeOwningMutableAddressor)
|
||||
CONTEXT_NODE(NativePinningAddressor)
|
||||
CONTEXT_NODE(NativePinningMutableAddressor)
|
||||
NODE(NominalTypeDescriptor)
|
||||
NODE(NonObjCAttribute)
|
||||
NODE(NonVariadicTuple)
|
||||
NODE(Number)
|
||||
NODE(ObjCAttribute)
|
||||
NODE(ObjCBlock)
|
||||
CONTEXT_NODE(OwningAddressor)
|
||||
CONTEXT_NODE(OwningMutableAddressor)
|
||||
NODE(PartialApplyForwarder)
|
||||
NODE(PartialApplyObjCForwarder)
|
||||
NODE(PostfixOperator)
|
||||
NODE(PrefixOperator)
|
||||
NODE(PrivateDeclName)
|
||||
CONTEXT_NODE(Protocol)
|
||||
NODE(ProtocolConformance)
|
||||
NODE(ProtocolDescriptor)
|
||||
NODE(ProtocolList)
|
||||
NODE(ProtocolWitness)
|
||||
NODE(ProtocolWitnessTable)
|
||||
NODE(ProtocolWitnessTableAccessor)
|
||||
NODE(QualifiedArchetype)
|
||||
NODE(ReabstractionThunk)
|
||||
NODE(ReabstractionThunkHelper)
|
||||
NODE(ReturnType)
|
||||
NODE(SILBoxType)
|
||||
NODE(SelfTypeRef)
|
||||
CONTEXT_NODE(Setter)
|
||||
NODE(SpecializationPassID)
|
||||
NODE(SpecializationIsFragile)
|
||||
CONTEXT_NODE(Static)
|
||||
CONTEXT_NODE(Structure)
|
||||
CONTEXT_NODE(Subscript)
|
||||
NODE(Suffix)
|
||||
NODE(ThinFunctionType)
|
||||
NODE(TupleElement)
|
||||
NODE(TupleElementName)
|
||||
NODE(Type)
|
||||
NODE(TypeAlias)
|
||||
NODE(TypeList)
|
||||
NODE(TypeMangling)
|
||||
NODE(TypeMetadata)
|
||||
NODE(TypeMetadataAccessFunction)
|
||||
NODE(TypeMetadataLazyCache)
|
||||
NODE(UncurriedFunctionType)
|
||||
NODE(Unmanaged)
|
||||
NODE(Unowned)
|
||||
CONTEXT_NODE(UnsafeAddressor)
|
||||
CONTEXT_NODE(UnsafeMutableAddressor)
|
||||
NODE(ValueWitness)
|
||||
NODE(ValueWitnessTable)
|
||||
CONTEXT_NODE(Variable)
|
||||
NODE(VariadicTuple)
|
||||
NODE(VTableAttribute)
|
||||
NODE(Weak)
|
||||
CONTEXT_NODE(WillSet)
|
||||
NODE(WitnessTableOffset)
|
||||
NODE(ThrowsAnnotation)
|
||||
|
||||
#undef CONTEXT_NODE
|
||||
#undef NODE
|
||||
@@ -0,0 +1,39 @@
|
||||
//===--- Fallthrough.h - switch fallthrough annotation macro ----*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines a SWIFT_FALLTHROUGH macro to annotate intentional
|
||||
// fallthrough between switch cases. For compilers that support the
|
||||
// "clang::fallthrough" attribute, it expands to an empty statement with the
|
||||
// attribute applied; otherwise, it expands to just an empty statement.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_BASIC_FALLTHROUGH_H
|
||||
#define SWIFT_BASIC_FALLTHROUGH_H
|
||||
|
||||
#ifndef __has_attribute
|
||||
# define __has_attribute(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef __has_cpp_attribute
|
||||
# define __has_cpp_attribute(x) 0
|
||||
#endif
|
||||
|
||||
#if __has_attribute(fallthrough)
|
||||
# define SWIFT_FALLTHROUGH [[clang::fallthrough]]
|
||||
#elif __has_cpp_attribute(clang::fallthrough)
|
||||
# define SWIFT_FALLTHROUGH [[clang::fallthrough]]
|
||||
#else
|
||||
# define SWIFT_FALLTHROUGH
|
||||
#endif
|
||||
|
||||
#endif // SWIFT_BASIC_FALLTHROUGH_H
|
||||
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// KSCString.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2013-02-23.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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/Foundation.h>
|
||||
|
||||
/**
|
||||
* A string, stored C style with null termination.
|
||||
*/
|
||||
@interface KSCString : NSObject
|
||||
|
||||
/** Length of the string in bytes (not characters!). Length does not include null terminator. */
|
||||
@property(nonatomic,readonly,assign) NSUInteger length;
|
||||
|
||||
/** String contents, including null terminator */
|
||||
@property(nonatomic,readonly,assign) const char* bytes;
|
||||
|
||||
/** Constructor for NSString */
|
||||
+ (KSCString*) stringWithString:(NSString*) string;
|
||||
|
||||
/** Constructor for null-terminated C string (assumes UTF-8 encoding). */
|
||||
+ (KSCString*) stringWithCString:(const char*) string;
|
||||
|
||||
/** Constructor for string contained in NSData (assumes UTF-8 encoding). */
|
||||
+ (KSCString*) stringWithData:(NSData*) data;
|
||||
|
||||
/** Constructor for non-terminated string (assumes UTF-8 encoding). */
|
||||
+ (KSCString*) stringWithData:(const char*) data length:(NSUInteger) length;
|
||||
|
||||
- (id) initWithString:(NSString*) string;
|
||||
- (id) initWithCString:(const char*) string;
|
||||
- (id) initWithData:(NSData*) data;
|
||||
- (id) initWithData:(const char*) data length:(NSUInteger) length;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// KSCrashDoctor.h
|
||||
// KSCrash
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-11-10.
|
||||
// Copyright (c) 2012 Karl Stenerud. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface KSCrashDoctor : NSObject
|
||||
|
||||
+ (KSCrashDoctor*) doctor;
|
||||
|
||||
- (NSString*) diagnoseCrash:(NSDictionary*) crashReport;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// KSCrashMonitor.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-12.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/** Keeps watch for crashes and informs via callback when on occurs.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_KSCrashMonitor_h
|
||||
#define HDR_KSCrashMonitor_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include "KSCrashMonitorType.h"
|
||||
#include "KSThread.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct KSCrash_MonitorContext;
|
||||
|
||||
|
||||
// ============================================================================
|
||||
#pragma mark - External API -
|
||||
// ============================================================================
|
||||
|
||||
/** Set which monitors are active.
|
||||
*
|
||||
* @param monitorTypes Which monitors should be active.
|
||||
*/
|
||||
void kscm_setActiveMonitors(KSCrashMonitorType monitorTypes);
|
||||
|
||||
/** Get the currently active monitors.
|
||||
*/
|
||||
KSCrashMonitorType kscm_getActiveMonitors(void);
|
||||
|
||||
/** Set the callback to call when an event is captured.
|
||||
*
|
||||
* @param onEvent Called whenever an event is captured.
|
||||
*/
|
||||
void kscm_setEventCallback(void (*onEvent)(struct KSCrash_MonitorContext* monitorContext));
|
||||
|
||||
|
||||
// ============================================================================
|
||||
#pragma mark - Internal API -
|
||||
// ============================================================================
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*setEnabled)(bool isEnabled);
|
||||
bool (*isEnabled)(void);
|
||||
void (*addContextualInfoToEvent)(struct KSCrash_MonitorContext* eventContext);
|
||||
} KSCrashMonitorAPI;
|
||||
|
||||
/** Notify that a fatal exception has been captured.
|
||||
* This allows the system to take appropriate steps in preparation.
|
||||
*
|
||||
* @oaram isAsyncSafeEnvironment If true, only async-safe functions are allowed from now on.
|
||||
*/
|
||||
bool kscm_notifyFatalExceptionCaptured(bool isAsyncSafeEnvironment);
|
||||
|
||||
/** Start general exception processing.
|
||||
*
|
||||
* @oaram context Contextual information about the exception.
|
||||
*/
|
||||
void kscm_handleException(struct KSCrash_MonitorContext* context);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSCrashMonitor_h
|
||||
@@ -0,0 +1,139 @@
|
||||
//
|
||||
// KSCrashMonitor_AppState.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-05.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/* Manages persistent state information useful for crash reporting such as
|
||||
* number of sessions, session length, etc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_KSCrashMonitor_AppState_h
|
||||
#define HDR_KSCrashMonitor_AppState_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "KSCrashMonitor.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Saved data
|
||||
|
||||
/** Total active time elapsed since the last crash. */
|
||||
double activeDurationSinceLastCrash;
|
||||
|
||||
/** Total time backgrounded elapsed since the last crash. */
|
||||
double backgroundDurationSinceLastCrash;
|
||||
|
||||
/** Number of app launches since the last crash. */
|
||||
int launchesSinceLastCrash;
|
||||
|
||||
/** Number of sessions (launch, resume from suspend) since last crash. */
|
||||
int sessionsSinceLastCrash;
|
||||
|
||||
/** Total active time elapsed since launch. */
|
||||
double activeDurationSinceLaunch;
|
||||
|
||||
/** Total time backgrounded elapsed since launch. */
|
||||
double backgroundDurationSinceLaunch;
|
||||
|
||||
/** Number of sessions (launch, resume from suspend) since app launch. */
|
||||
int sessionsSinceLaunch;
|
||||
|
||||
/** If true, the application crashed on the previous launch. */
|
||||
bool crashedLastLaunch;
|
||||
|
||||
// Live data
|
||||
|
||||
/** If true, the application crashed on this launch. */
|
||||
bool crashedThisLaunch;
|
||||
|
||||
/** Timestamp for when the app state was last changed (active<->inactive,
|
||||
* background<->foreground) */
|
||||
double appStateTransitionTime;
|
||||
|
||||
/** If true, the application is currently active. */
|
||||
bool applicationIsActive;
|
||||
|
||||
/** If true, the application is currently in the foreground. */
|
||||
bool applicationIsInForeground;
|
||||
|
||||
} KSCrash_AppState;
|
||||
|
||||
|
||||
/** Initialize the state monitor.
|
||||
*
|
||||
* @param stateFilePath Where to store on-disk representation of state.
|
||||
*/
|
||||
void kscrashstate_initialize(const char* stateFilePath);
|
||||
|
||||
/** Reset the crash state.
|
||||
*/
|
||||
bool kscrashstate_reset(void);
|
||||
|
||||
/** Notify the crash reporter of KSCrash being added to Objective-C runtime system.
|
||||
*/
|
||||
void kscrashstate_notifyObjCLoad(void);
|
||||
|
||||
/** Notify the crash reporter of the application active state.
|
||||
*
|
||||
* @param isActive true if the application is active, otherwise false.
|
||||
*/
|
||||
void kscrashstate_notifyAppActive(bool isActive);
|
||||
|
||||
/** Notify the crash reporter of the application foreground/background state.
|
||||
*
|
||||
* @param isInForeground true if the application is in the foreground, false if
|
||||
* it is in the background.
|
||||
*/
|
||||
void kscrashstate_notifyAppInForeground(bool isInForeground);
|
||||
|
||||
/** Notify the crash reporter that the application is terminating.
|
||||
*/
|
||||
void kscrashstate_notifyAppTerminate(void);
|
||||
|
||||
/** Notify the crash reporter that the application has crashed.
|
||||
*/
|
||||
void kscrashstate_notifyAppCrash(void);
|
||||
|
||||
/** Read-only access into the current state.
|
||||
*/
|
||||
const KSCrash_AppState* const kscrashstate_currentState(void);
|
||||
|
||||
/** Access the Monitor API.
|
||||
*/
|
||||
KSCrashMonitorAPI* kscm_appstate_getAPI(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSCrashMonitor_AppState_h
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// KSCrashMonitor_CPPException.h
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef HDR_KSCrashMonitor_CPPException_h
|
||||
#define HDR_KSCrashMonitor_CPPException_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "KSCrashMonitor.h"
|
||||
|
||||
/** Enable swapping of __cxa_trow symbol with lazy symbols table
|
||||
*/
|
||||
void kscm_enableSwapCxaThrow(void);
|
||||
|
||||
/** Access the Monitor API.
|
||||
*/
|
||||
KSCrashMonitorAPI* kscm_cppexception_getAPI(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSCrashMonitor_CPPException_h
|
||||
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// KSCrashMonitor_Deadlock.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-12-09.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
/* Catches deadlocks in threads and queues.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_KSCrashMonitor_Deadlock_h
|
||||
#define HDR_KSCrashMonitor_Deadlock_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include "KSCrashMonitor.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
/** Set the interval between watchdog checks on the main thread.
|
||||
* Default is 5 seconds.
|
||||
*
|
||||
* @param value The number of seconds between checks (0 = disabled).
|
||||
*/
|
||||
void kscm_setDeadlockHandlerWatchdogInterval(double value);
|
||||
|
||||
/** Access the Monitor API.
|
||||
*/
|
||||
KSCrashMonitorAPI* kscm_deadlock_getAPI(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSCrashMonitor_Deadlock_h
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// KSCrashMonitor_MachException.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-04.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/* Catches mach exceptions.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_KSCrashMonitor_MachException_h
|
||||
#define HDR_KSCrashMonitor_MachException_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "KSCrashMonitor.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
/** Access the Monitor API.
|
||||
*/
|
||||
KSCrashMonitorAPI* kscm_machexception_getAPI(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSCrashMonitor_MachException_h
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// KSCrashMonitor_NSException.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-01-28.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/* Catches Objective-C exceptions.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_KSCrashMonitor_NSException_h
|
||||
#define HDR_KSCrashMonitor_NSException_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include "KSCrashMonitor.h"
|
||||
|
||||
|
||||
/** Access the Monitor API.
|
||||
*/
|
||||
KSCrashMonitorAPI* kscm_nsexception_getAPI(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSCrashMonitor_NSException_h
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// KSCrashMonitor_Signal.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-01-28.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/* Catches fatal unix signals.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_KSCrashMonitor_Signal_h
|
||||
#define HDR_KSCrashMonitor_Signal_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include "KSCrashMonitor.h"
|
||||
|
||||
|
||||
/** Access the Monitor API.
|
||||
*/
|
||||
KSCrashMonitorAPI* kscm_signal_getAPI(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSCrashMonitor_Signal_h
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// KSCrashMonitor_System.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-05.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef KSCrashMonitor_System_h
|
||||
#define KSCrashMonitor_System_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include "KSCrashMonitor.h"
|
||||
|
||||
|
||||
/** Access the Monitor API.
|
||||
*/
|
||||
KSCrashMonitorAPI* kscm_system_getAPI(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// KSCrashMonitor_User.h
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef HDR_KSCrashMonitor_User_h
|
||||
#define HDR_KSCrashMonitor_User_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include "KSCrashMonitor.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
/** Report a custom, user defined exception.
|
||||
* If terminateProgram is true, all sentries will be uninstalled and the application will
|
||||
* terminate with an abort().
|
||||
*
|
||||
* @param name The exception name (for namespacing exception types).
|
||||
*
|
||||
* @param reason A description of why the exception occurred.
|
||||
*
|
||||
* @param language A unique language identifier.
|
||||
*
|
||||
* @param lineOfCode A copy of the offending line of code (NULL = ignore).
|
||||
*
|
||||
* @param stackTrace JSON encoded array containing stack trace information (one frame per array entry).
|
||||
* The frame structure can be anything you want, including bare strings.
|
||||
*
|
||||
* @param logAllThreads If true, suspend all threads and log their state. Note that this incurs a
|
||||
* performance penalty, so it's best to use only on fatal errors.
|
||||
*
|
||||
* @param terminateProgram If true, do not return from this function call. Terminate the program instead.
|
||||
*/
|
||||
void kscm_reportUserException(const char* name,
|
||||
const char* reason,
|
||||
const char* language,
|
||||
const char* lineOfCode,
|
||||
const char* stackTrace,
|
||||
bool logAllThreads,
|
||||
bool terminateProgram);
|
||||
|
||||
/** Access the Monitor API.
|
||||
*/
|
||||
KSCrashMonitorAPI* kscm_user_getAPI(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSCrashMonitor_User_h
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// KSCrashMonitor_Zombie.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-09-15.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/* Poor man's zombie tracking.
|
||||
*
|
||||
* Benefits:
|
||||
* - Very low CPU overhead.
|
||||
* - Low memory overhead.
|
||||
*
|
||||
* Limitations:
|
||||
* - Not guaranteed to catch all zombies.
|
||||
* - Can generate false positives or incorrect class names.
|
||||
* - KSZombie itself must be compiled with ARC disabled. You can enable ARC in
|
||||
* your app, but KSZombie must be compiled in a separate library if you do.
|
||||
*/
|
||||
|
||||
#ifndef HDR_KSZombie_h
|
||||
#define HDR_KSZombie_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "KSCrashMonitor.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
/** Get the class of a deallocated object pointer, if it was tracked.
|
||||
*
|
||||
* @param object A pointer to a deallocated object.
|
||||
*
|
||||
* @return The object's class name, or NULL if it wasn't found.
|
||||
*/
|
||||
const char* kszombie_className(const void* object);
|
||||
|
||||
/** Access the Monitor API.
|
||||
*/
|
||||
KSCrashMonitorAPI* kscm_zombie_getAPI(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSZombie_h
|
||||
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// KSCrashReport.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-01-28.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/* Writes a crash report to disk.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_KSCrashReport_h
|
||||
#define HDR_KSCrashReport_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#import "KSCrashReportWriter.h"
|
||||
#import "KSCrashMonitorContext.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
// ============================================================================
|
||||
#pragma mark - Configuration -
|
||||
// ============================================================================
|
||||
|
||||
/** Set custom user information to be stored in the report.
|
||||
*
|
||||
* @param userInfoJSON The user information, in JSON format.
|
||||
*/
|
||||
void kscrashreport_setUserInfoJSON(const char* const userInfoJSON);
|
||||
|
||||
/** Configure whether to introspect any interesting memory locations.
|
||||
* This can find things like strings or Objective-C classes.
|
||||
*
|
||||
* @param shouldIntrospectMemory If true, introspect memory.
|
||||
*/
|
||||
void kscrashreport_setIntrospectMemory(bool shouldIntrospectMemory);
|
||||
|
||||
/** Specify which objective-c classes should not be introspected.
|
||||
*
|
||||
* @param doNotIntrospectClasses Array of class names.
|
||||
* @param length Length of the array.
|
||||
*/
|
||||
void kscrashreport_setDoNotIntrospectClasses(const char** doNotIntrospectClasses, int length);
|
||||
|
||||
/** Set the function to call when writing the user section of the report.
|
||||
* This allows the user to add more fields to the user section at the time of the crash.
|
||||
* Note: Only async-safe functions are allowed in the callback.
|
||||
*
|
||||
* @param userSectionWriteCallback The user section write callback.
|
||||
*/
|
||||
void kscrashreport_setUserSectionWriteCallback(const KSReportWriteCallback userSectionWriteCallback);
|
||||
|
||||
|
||||
// ============================================================================
|
||||
#pragma mark - Main API -
|
||||
// ============================================================================
|
||||
|
||||
/** Write a standard crash report to a file.
|
||||
*
|
||||
* @param monitorContext Contextual information about the crash and environment.
|
||||
* The caller must fill this out before passing it in.
|
||||
*
|
||||
* @param path The file to write to.
|
||||
*/
|
||||
void kscrashreport_writeStandardReport(const struct KSCrash_MonitorContext* const monitorContext,
|
||||
const char* path);
|
||||
|
||||
/** Write a minimal crash report to a file.
|
||||
*
|
||||
* @param monitorContext Contextual information about the crash and environment.
|
||||
* The caller must fill this out before passing it in.
|
||||
*
|
||||
* @param path The file to write to.
|
||||
*/
|
||||
void kscrashreport_writeRecrashReport(const struct KSCrash_MonitorContext* const monitorContext,
|
||||
const char* path);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSCrashReport_h
|
||||
@@ -0,0 +1,229 @@
|
||||
//
|
||||
// KSCrashReportFields.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-10-07.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
#ifndef HDR_KSCrashReportFields_h
|
||||
#define HDR_KSCrashReportFields_h
|
||||
|
||||
|
||||
#pragma mark - Report Types -
|
||||
|
||||
#define KSCrashReportType_Minimal "minimal"
|
||||
#define KSCrashReportType_Standard "standard"
|
||||
#define KSCrashReportType_Custom "custom"
|
||||
|
||||
|
||||
#pragma mark - Memory Types -
|
||||
|
||||
#define KSCrashMemType_Block "objc_block"
|
||||
#define KSCrashMemType_Class "objc_class"
|
||||
#define KSCrashMemType_NullPointer "null_pointer"
|
||||
#define KSCrashMemType_Object "objc_object"
|
||||
#define KSCrashMemType_String "string"
|
||||
#define KSCrashMemType_Unknown "unknown"
|
||||
|
||||
|
||||
#pragma mark - Exception Types -
|
||||
|
||||
#define KSCrashExcType_CPPException "cpp_exception"
|
||||
#define KSCrashExcType_Deadlock "deadlock"
|
||||
#define KSCrashExcType_Mach "mach"
|
||||
#define KSCrashExcType_NSException "nsexception"
|
||||
#define KSCrashExcType_Signal "signal"
|
||||
#define KSCrashExcType_User "user"
|
||||
|
||||
|
||||
#pragma mark - Common -
|
||||
|
||||
#define KSCrashField_Address "address"
|
||||
#define KSCrashField_Contents "contents"
|
||||
#define KSCrashField_Exception "exception"
|
||||
#define KSCrashField_FirstObject "first_object"
|
||||
#define KSCrashField_Index "index"
|
||||
#define KSCrashField_Ivars "ivars"
|
||||
#define KSCrashField_Language "language"
|
||||
#define KSCrashField_Name "name"
|
||||
#define KSCrashField_UserInfo "userInfo"
|
||||
#define KSCrashField_ReferencedObject "referenced_object"
|
||||
#define KSCrashField_Type "type"
|
||||
#define KSCrashField_UUID "uuid"
|
||||
#define KSCrashField_Value "value"
|
||||
|
||||
#define KSCrashField_Error "error"
|
||||
#define KSCrashField_JSONData "json_data"
|
||||
|
||||
|
||||
#pragma mark - Notable Address -
|
||||
|
||||
#define KSCrashField_Class "class"
|
||||
#define KSCrashField_LastDeallocObject "last_deallocated_obj"
|
||||
|
||||
|
||||
#pragma mark - Backtrace -
|
||||
|
||||
#define KSCrashField_InstructionAddr "instruction_addr"
|
||||
#define KSCrashField_LineOfCode "line_of_code"
|
||||
#define KSCrashField_ObjectAddr "object_addr"
|
||||
#define KSCrashField_ObjectName "object_name"
|
||||
#define KSCrashField_SymbolAddr "symbol_addr"
|
||||
#define KSCrashField_SymbolName "symbol_name"
|
||||
|
||||
|
||||
#pragma mark - Stack Dump -
|
||||
|
||||
#define KSCrashField_DumpEnd "dump_end"
|
||||
#define KSCrashField_DumpStart "dump_start"
|
||||
#define KSCrashField_GrowDirection "grow_direction"
|
||||
#define KSCrashField_Overflow "overflow"
|
||||
#define KSCrashField_StackPtr "stack_pointer"
|
||||
|
||||
|
||||
#pragma mark - Thread Dump -
|
||||
|
||||
#define KSCrashField_Backtrace "backtrace"
|
||||
#define KSCrashField_Basic "basic"
|
||||
#define KSCrashField_Crashed "crashed"
|
||||
#define KSCrashField_CurrentThread "current_thread"
|
||||
#define KSCrashField_DispatchQueue "dispatch_queue"
|
||||
#define KSCrashField_NotableAddresses "notable_addresses"
|
||||
#define KSCrashField_Registers "registers"
|
||||
#define KSCrashField_Skipped "skipped"
|
||||
#define KSCrashField_Stack "stack"
|
||||
|
||||
|
||||
#pragma mark - Binary Image -
|
||||
|
||||
#define KSCrashField_CPUSubType "cpu_subtype"
|
||||
#define KSCrashField_CPUType "cpu_type"
|
||||
#define KSCrashField_ImageAddress "image_addr"
|
||||
#define KSCrashField_ImageVmAddress "image_vmaddr"
|
||||
#define KSCrashField_ImageSize "image_size"
|
||||
#define KSCrashField_ImageMajorVersion "major_version"
|
||||
#define KSCrashField_ImageMinorVersion "minor_version"
|
||||
#define KSCrashField_ImageRevisionVersion "revision_version"
|
||||
#define KSCrashField_ImageCrashInfoMessage "crash_info_message"
|
||||
#define KSCrashField_ImageCrashInfoMessage2 "crash_info_message2"
|
||||
|
||||
|
||||
#pragma mark - Memory -
|
||||
|
||||
#define KSCrashField_Free "free"
|
||||
#define KSCrashField_Usable "usable"
|
||||
|
||||
|
||||
#pragma mark - Error -
|
||||
|
||||
#define KSCrashField_Backtrace "backtrace"
|
||||
#define KSCrashField_Code "code"
|
||||
#define KSCrashField_CodeName "code_name"
|
||||
#define KSCrashField_CPPException "cpp_exception"
|
||||
#define KSCrashField_ExceptionName "exception_name"
|
||||
#define KSCrashField_Mach "mach"
|
||||
#define KSCrashField_NSException "nsexception"
|
||||
#define KSCrashField_Reason "reason"
|
||||
#define KSCrashField_Signal "signal"
|
||||
#define KSCrashField_Subcode "subcode"
|
||||
#define KSCrashField_UserReported "user_reported"
|
||||
|
||||
|
||||
#pragma mark - Process State -
|
||||
|
||||
#define KSCrashField_LastDeallocedNSException "last_dealloced_nsexception"
|
||||
#define KSCrashField_ProcessState "process"
|
||||
|
||||
|
||||
#pragma mark - App Stats -
|
||||
|
||||
#define KSCrashField_ActiveTimeSinceCrash "active_time_since_last_crash"
|
||||
#define KSCrashField_ActiveTimeSinceLaunch "active_time_since_launch"
|
||||
#define KSCrashField_AppActive "application_active"
|
||||
#define KSCrashField_AppInFG "application_in_foreground"
|
||||
#define KSCrashField_BGTimeSinceCrash "background_time_since_last_crash"
|
||||
#define KSCrashField_BGTimeSinceLaunch "background_time_since_launch"
|
||||
#define KSCrashField_LaunchesSinceCrash "launches_since_last_crash"
|
||||
#define KSCrashField_SessionsSinceCrash "sessions_since_last_crash"
|
||||
#define KSCrashField_SessionsSinceLaunch "sessions_since_launch"
|
||||
|
||||
|
||||
#pragma mark - Report -
|
||||
|
||||
#define KSCrashField_Crash "crash"
|
||||
#define KSCrashField_Debug "debug"
|
||||
#define KSCrashField_Diagnosis "diagnosis"
|
||||
#define KSCrashField_ID "id"
|
||||
#define KSCrashField_ProcessName "process_name"
|
||||
#define KSCrashField_Report "report"
|
||||
#define KSCrashField_Timestamp "timestamp"
|
||||
#define KSCrashField_Version "version"
|
||||
|
||||
#pragma mark Minimal
|
||||
#define KSCrashField_CrashedThread "crashed_thread"
|
||||
|
||||
#pragma mark Standard
|
||||
#define KSCrashField_AppStats "application_stats"
|
||||
#define KSCrashField_BinaryImages "binary_images"
|
||||
#define KSCrashField_System "system"
|
||||
#define KSCrashField_Memory "memory"
|
||||
#define KSCrashField_Threads "threads"
|
||||
#define KSCrashField_User "user"
|
||||
#define KSCrashField_ConsoleLog "console_log"
|
||||
|
||||
#pragma mark Incomplete
|
||||
#define KSCrashField_Incomplete "incomplete"
|
||||
#define KSCrashField_RecrashReport "recrash_report"
|
||||
|
||||
#pragma mark System
|
||||
#define KSCrashField_AppStartTime "app_start_time"
|
||||
#define KSCrashField_AppUUID "app_uuid"
|
||||
#define KSCrashField_BootTime "boot_time"
|
||||
#define KSCrashField_BundleID "CFBundleIdentifier"
|
||||
#define KSCrashField_BundleName "CFBundleName"
|
||||
#define KSCrashField_BundleShortVersion "CFBundleShortVersionString"
|
||||
#define KSCrashField_BundleVersion "CFBundleVersion"
|
||||
#define KSCrashField_CPUArch "cpu_arch"
|
||||
#define KSCrashField_CPUType "cpu_type"
|
||||
#define KSCrashField_CPUSubType "cpu_subtype"
|
||||
#define KSCrashField_BinaryCPUType "binary_cpu_type"
|
||||
#define KSCrashField_BinaryCPUSubType "binary_cpu_subtype"
|
||||
#define KSCrashField_DeviceAppHash "device_app_hash"
|
||||
#define KSCrashField_Executable "CFBundleExecutable"
|
||||
#define KSCrashField_ExecutablePath "CFBundleExecutablePath"
|
||||
#define KSCrashField_Jailbroken "jailbroken"
|
||||
#define KSCrashField_KernelVersion "kernel_version"
|
||||
#define KSCrashField_Machine "machine"
|
||||
#define KSCrashField_Model "model"
|
||||
#define KSCrashField_OSVersion "os_version"
|
||||
#define KSCrashField_ParentProcessID "parent_process_id"
|
||||
#define KSCrashField_ProcessID "process_id"
|
||||
#define KSCrashField_ProcessName "process_name"
|
||||
#define KSCrashField_Size "size"
|
||||
#define KSCrashField_Storage "storage"
|
||||
#define KSCrashField_SystemName "system_name"
|
||||
#define KSCrashField_SystemVersion "system_version"
|
||||
#define KSCrashField_TimeZone "time_zone"
|
||||
#define KSCrashField_BuildType "build_type"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// KSCrashReportFixer.c
|
||||
//
|
||||
// Created by Karl Stenerud on 2016-11-07.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef HDR_KSCrashReportFixer_h
|
||||
#define HDR_KSCrashReportFixer_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** Fixes up fields in a crash report that could not be fixed up at crash time.
|
||||
* Some fields, such a mangled fields and dates, cannot be fixed up at crash time
|
||||
* because the function calls needed to do it are not async-safe.
|
||||
*
|
||||
* @param crashReport A raw report loaded from disk.
|
||||
*
|
||||
* @return A fixed up crash report.
|
||||
* MEMORY MANAGEMENT WARNING: User is responsible for calling free() on the returned value.
|
||||
*/
|
||||
char* kscrf_fixupCrashReport(const char* crashReport);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSCrashReportFixer_h
|
||||
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// KSCrashReportStore.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-05.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef HDR_KSCrashReportStore_h
|
||||
#define HDR_KSCrashReportStore_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define KSCRS_MAX_PATH_LENGTH 500
|
||||
|
||||
/** Initialize the report store.
|
||||
*
|
||||
* @param appName The application's name.
|
||||
* @param reportsPath Full path to directory where the reports are to be stored (path will be created if needed).
|
||||
*/
|
||||
void kscrs_initialize(const char* appName, const char* reportsPath);
|
||||
|
||||
/** Get the next crash report to be generated.
|
||||
* Max length for paths is KSCRS_MAX_PATH_LENGTH
|
||||
*
|
||||
* @param crashReportPathBuffer Buffer to store the crash report path.
|
||||
*
|
||||
* @return the report ID of the next report.
|
||||
*/
|
||||
int64_t kscrs_getNextCrashReport(char* crashReportPathBuffer);
|
||||
|
||||
/** Get the number of reports on disk.
|
||||
*/
|
||||
int kscrs_getReportCount(void);
|
||||
|
||||
/** Get a list of IDs for all reports on disk.
|
||||
*
|
||||
* @param reportIDs An array big enough to hold all report IDs.
|
||||
* @param count How many reports the array can hold.
|
||||
*
|
||||
* @return The number of report IDs that were placed in the array.
|
||||
*/
|
||||
int kscrs_getReportIDs(int64_t* reportIDs, int count);
|
||||
|
||||
/** Read a report.
|
||||
*
|
||||
* @param reportID The report's ID.
|
||||
*
|
||||
* @return The NULL terminated report, or NULL if not found.
|
||||
* MEMORY MANAGEMENT WARNING: User is responsible for calling free() on the returned value.
|
||||
*/
|
||||
char* kscrs_readReport(int64_t reportID);
|
||||
|
||||
/** Add a custom report to the store.
|
||||
*
|
||||
* @param report The report's contents (must be JSON encoded).
|
||||
* @param reportLength The length of the report in bytes.
|
||||
*
|
||||
* @return the new report's ID.
|
||||
*/
|
||||
int64_t kscrs_addUserReport(const char* report, int reportLength);
|
||||
|
||||
/** Delete all reports on disk.
|
||||
*/
|
||||
void kscrs_deleteAllReports(void);
|
||||
|
||||
/** Delete report.
|
||||
*
|
||||
* @param reportID An ID of report to delete.
|
||||
*/
|
||||
void kscrs_deleteReportWithID(int64_t reportID);
|
||||
|
||||
/** Set the maximum number of reports allowed on disk before old ones get deleted.
|
||||
*
|
||||
* @param maxReportCount The maximum number of reports.
|
||||
*/
|
||||
void kscrs_setMaxReportCount(int maxReportCount);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSCrashReportStore_h
|
||||
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// KSCrashReportVersion.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2016-03-10.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef HDR_KSCrashReportVersion_h
|
||||
#define HDR_KSCrashReportVersion_h
|
||||
|
||||
#define KSCRASH_REPORT_VERSION "3.3.0"
|
||||
|
||||
#endif /* HDR_KSCrashReportVersion_h */
|
||||
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// KSDate.h
|
||||
//
|
||||
// Copyright 2016 Karl Stenerud.
|
||||
//
|
||||
// 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef KSDate_h
|
||||
#define KSDate_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/** Convert a UNIX timestamp to an RFC3339 string representation.
|
||||
*
|
||||
* @param timestamp The date to convert.
|
||||
*
|
||||
* @param buffer21Chars A buffer of at least 21 chars to hold the RFC3339 date string.
|
||||
*/
|
||||
void ksdate_utcStringFromTimestamp(time_t timestamp, char* buffer21Chars);
|
||||
|
||||
/** Convert microseconds returned from `gettimeofday` to an RFC3339 string representation.
|
||||
*
|
||||
* @param microseconds The microseconds to convert.
|
||||
*
|
||||
* @param buffer28Chars A buffer of at least 28 chars to hold the RFC3339 date string with milliseconds precision.
|
||||
*/
|
||||
void ksdate_utcStringFromMicroseconds(int64_t microseconds, char* buffer28Chars);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* KSDate_h */
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// KSDemangle_CPP.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2016-11-04.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef HDR_KSDemangle_CPP_h
|
||||
#define HDR_KSDemangle_CPP_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Demangle a C++ symbol.
|
||||
*
|
||||
* @param mangledSymbol The mangled symbol.
|
||||
*
|
||||
* @return A demangled symbol, or NULL if demangling failed.
|
||||
* MEMORY MANAGEMENT WARNING: User is responsible for calling free() on the returned value.
|
||||
*/
|
||||
char* ksdm_demangleCPP(const char* mangledSymbol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSDemangle_CPP_h
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// KSDemangle_Swift.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2016-11-04.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef HDR_KSDemangle_Swift_h
|
||||
#define HDR_KSDemangle_Swift_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Demangle a Swift symbol.
|
||||
*
|
||||
* @param mangledSymbol The mangled symbol.
|
||||
*
|
||||
* @return A demangled symbol, or NULL if demangling failed.
|
||||
* MEMORY MANAGEMENT WARNING: User is responsible for calling free() on the returned value.
|
||||
*/
|
||||
char* ksdm_demangleSwift(const char* mangledSymbol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSDemangle_Swift_h
|
||||
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// KSDynamicLinker.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2013-10-02.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef HDR_KSDynamicLinker_h
|
||||
#define HDR_KSDynamicLinker_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t address;
|
||||
uint64_t vmAddress;
|
||||
uint64_t size;
|
||||
const char* name;
|
||||
const uint8_t* uuid;
|
||||
int cpuType;
|
||||
int cpuSubType;
|
||||
uint64_t majorVersion;
|
||||
uint64_t minorVersion;
|
||||
uint64_t revisionVersion;
|
||||
const char* crashInfoMessage;
|
||||
const char* crashInfoMessage2;
|
||||
} KSBinaryImage;
|
||||
|
||||
/** Get the number of loaded binary images.
|
||||
*/
|
||||
int ksdl_imageCount(void);
|
||||
|
||||
/** Get information about a binary image.
|
||||
*
|
||||
* @param index The binary index.
|
||||
*
|
||||
* @param buffer A structure to hold the information.
|
||||
*
|
||||
* @return True if the image was successfully queried.
|
||||
*/
|
||||
bool ksdl_getBinaryImage(int index, KSBinaryImage* buffer);
|
||||
|
||||
/** Get information about a binary image based on mach_header.
|
||||
*
|
||||
* @param header_ptr The pointer to mach_header of the image.
|
||||
*
|
||||
* @param image_name The name of the image.
|
||||
*
|
||||
* @param buffer A structure to hold the information.
|
||||
*
|
||||
* @return True if the image was successfully queried.
|
||||
*/
|
||||
bool ksdl_getBinaryImageForHeader(const void* const header_ptr, const char* const image_name, KSBinaryImage* buffer);
|
||||
|
||||
/** Find a loaded binary image with the specified name.
|
||||
*
|
||||
* @param imageName The image name to look for.
|
||||
*
|
||||
* @param exactMatch If true, look for an exact match instead of a partial one.
|
||||
*
|
||||
* @return the index of the matched image, or UINT32_MAX if not found.
|
||||
*/
|
||||
uint32_t ksdl_imageNamed(const char* const imageName, bool exactMatch);
|
||||
|
||||
/** Get the UUID of a loaded binary image with the specified name.
|
||||
*
|
||||
* @param imageName The image name to look for.
|
||||
*
|
||||
* @param exactMatch If true, look for an exact match instead of a partial one.
|
||||
*
|
||||
* @return A pointer to the binary (16 byte) UUID of the image, or NULL if it
|
||||
* wasn't found.
|
||||
*/
|
||||
const uint8_t* ksdl_imageUUID(const char* const imageName, bool exactMatch);
|
||||
|
||||
/** async-safe version of dladdr.
|
||||
*
|
||||
* This method searches the dynamic loader for information about any image
|
||||
* containing the specified address. It may not be entirely successful in
|
||||
* finding information, in which case any fields it could not find will be set
|
||||
* to NULL.
|
||||
*
|
||||
* Unlike dladdr(), this method does not make use of locks, and does not call
|
||||
* async-unsafe functions.
|
||||
*
|
||||
* @param address The address to search for.
|
||||
* @param info Gets filled out by this function.
|
||||
* @return true if at least some information was found.
|
||||
*/
|
||||
bool ksdl_dladdr(const uintptr_t address, Dl_info* const info);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSDynamicLinker_h
|
||||
@@ -0,0 +1,276 @@
|
||||
//
|
||||
// KSFileUtils.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-01-28.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/* Basic file reading/writing functions.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_KSFileUtils_h
|
||||
#define HDR_KSFileUtils_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
#define KSFU_MAX_PATH_LENGTH 500
|
||||
|
||||
/** Get the last entry in a file path. Assumes UNIX style separators.
|
||||
*
|
||||
* @param path The file path.
|
||||
*
|
||||
* @return the last entry in the path.
|
||||
*/
|
||||
const char* ksfu_lastPathEntry(const char* path);
|
||||
|
||||
/** Write bytes to a file descriptor.
|
||||
*
|
||||
* @param fd The file descriptor.
|
||||
*
|
||||
* @param bytes Buffer containing the bytes.
|
||||
*
|
||||
* @param length The number of bytes to write.
|
||||
*
|
||||
* @return true if the operation was successful.
|
||||
*/
|
||||
bool ksfu_writeBytesToFD(const int fd, const char* bytes, int length);
|
||||
|
||||
/** Read bytes from a file descriptor.
|
||||
*
|
||||
* @param fd The file descriptor.
|
||||
*
|
||||
* @param bytes Buffer to store the bytes in.
|
||||
*
|
||||
* @param length The number of bytes to read.
|
||||
*
|
||||
* @return true if the operation was successful.
|
||||
*/
|
||||
bool ksfu_readBytesFromFD(const int fd, char* bytes, int length);
|
||||
|
||||
/** Read an entire file. Returns a buffer of file size + 1, null terminated.
|
||||
*
|
||||
* @param path The path to the file.
|
||||
*
|
||||
* @param data Place to store a pointer to the loaded data (must be freed).
|
||||
*
|
||||
* @param length Place to store the length of the loaded data (can be NULL).
|
||||
*
|
||||
* @param maxLength the maximum amount of bytes to read. It will skip beginning
|
||||
* bytes if necessary, and always get the latter part of the file.
|
||||
* 0 = no maximum.
|
||||
*
|
||||
* @return true if the operation was successful.
|
||||
*/
|
||||
bool ksfu_readEntireFile(const char* path, char** data, int* length, int maxLength);
|
||||
|
||||
/** Write a string to a file.
|
||||
*
|
||||
* @param fd The file descriptor.
|
||||
*
|
||||
* @param string The string to write.
|
||||
*
|
||||
* @return true if successful.
|
||||
*/
|
||||
bool ksfu_writeStringToFD(const int fd, const char* string);
|
||||
|
||||
/** Write a formatted string to a file.
|
||||
*
|
||||
* @param fd The file descriptor.
|
||||
*
|
||||
* @param fmt The format specifier, followed by its arguments.
|
||||
*
|
||||
* @return true if successful.
|
||||
*/
|
||||
bool ksfu_writeFmtToFD(const int fd, const char* fmt, ...);
|
||||
|
||||
/** Write a formatted string to a file.
|
||||
*
|
||||
* @param fd The file descriptor.
|
||||
*
|
||||
* @param fmt The format specifier.
|
||||
*
|
||||
* @param args The arguments list.
|
||||
*
|
||||
* @return true if successful.
|
||||
*/
|
||||
bool ksfu_writeFmtArgsToFD(const int fd, const char* fmt, va_list args);
|
||||
|
||||
/** Read a single line from a file.
|
||||
*
|
||||
* @param fd The file descriptor.
|
||||
*
|
||||
* @param buffer The buffer to read into.
|
||||
*
|
||||
* @param maxLength The maximum length to read.
|
||||
*
|
||||
* @return The number of bytes read.
|
||||
*/
|
||||
int ksfu_readLineFromFD(const int fd, char* buffer, int maxLength);
|
||||
|
||||
/** Make all directories in a path.
|
||||
*
|
||||
* @param absolutePath The full, absolute path to create.
|
||||
*
|
||||
* @return true if successful.
|
||||
*/
|
||||
bool ksfu_makePath(const char* absolutePath);
|
||||
|
||||
/** Remove a file or directory.
|
||||
*
|
||||
* @param path Path to the file to remove.
|
||||
*
|
||||
* @param mustExist If true, and the path doesn't exist, log an error.
|
||||
*
|
||||
* @return true if successful.
|
||||
*/
|
||||
bool ksfu_removeFile(const char* path, bool mustExist);
|
||||
|
||||
/** Delete the contents of a directory.
|
||||
*
|
||||
* @param path The path of the directory whose contents to delete.
|
||||
*
|
||||
* @return true if successful.
|
||||
*/
|
||||
bool ksfu_deleteContentsOfPath(const char* path);
|
||||
|
||||
/** Buffered writer structure. Everything inside should be considered internal use only. */
|
||||
typedef struct
|
||||
{
|
||||
char* buffer;
|
||||
int bufferLength;
|
||||
int position;
|
||||
int fd;
|
||||
} KSBufferedWriter;
|
||||
|
||||
/** Open a file for buffered writing.
|
||||
*
|
||||
* @param writer The writer to initialize.
|
||||
*
|
||||
* @param path The path of the file to open.
|
||||
*
|
||||
* @param writeBuffer Memory to use as the write buffer.
|
||||
*
|
||||
* @param writeBufferLength Length of the memory to use as the write buffer.
|
||||
*
|
||||
* @return True if the file was successfully opened.
|
||||
*/
|
||||
bool ksfu_openBufferedWriter(KSBufferedWriter* writer, const char* const path, char* writeBuffer, int writeBufferLength);
|
||||
|
||||
/** Close a buffered writer.
|
||||
*
|
||||
* @param writer The writer to close.
|
||||
*/
|
||||
void ksfu_closeBufferedWriter(KSBufferedWriter* writer);
|
||||
|
||||
/** Write to a buffered writer.
|
||||
*
|
||||
* @param writer The writer to write to.
|
||||
*
|
||||
* @param data The data to write.
|
||||
*
|
||||
* @param length The length of the data to write.
|
||||
*
|
||||
* @return True if the data was successfully written.
|
||||
*/
|
||||
bool ksfu_writeBufferedWriter(KSBufferedWriter* writer, const char* restrict const data, const int length);
|
||||
|
||||
/** Flush a buffered writer, writing all uncommitted data to disk.
|
||||
*
|
||||
* @param writer The writer to flush.
|
||||
*
|
||||
* @return True if the buffer was successfully flushed.
|
||||
*/
|
||||
bool ksfu_flushBufferedWriter(KSBufferedWriter* writer);
|
||||
|
||||
/** Buffered reader structure. Everything inside should be considered internal use only. */
|
||||
typedef struct
|
||||
{
|
||||
char* buffer;
|
||||
int bufferLength;
|
||||
int dataStartPos;
|
||||
int dataEndPos;
|
||||
int fd;
|
||||
} KSBufferedReader;
|
||||
|
||||
/** Open a file for buffered reading.
|
||||
*
|
||||
* @param reader The reader to initialize.
|
||||
*
|
||||
* @param path The path to the file to open.
|
||||
*
|
||||
* @param readBuffer The memory to use for buffered reading.
|
||||
*
|
||||
* @param readBufferLength The length of the memory to use for buffered reading.
|
||||
*
|
||||
* @return True if the file was successfully opened.
|
||||
*/
|
||||
bool ksfu_openBufferedReader(KSBufferedReader* reader, const char* const path, char* readBuffer, int readBufferLength);
|
||||
|
||||
/** Close a buffered reader.
|
||||
*
|
||||
* @param reader The reader to close.
|
||||
*/
|
||||
void ksfu_closeBufferedReader(KSBufferedReader* reader);
|
||||
|
||||
/** Read from a buffered reader.
|
||||
*
|
||||
* @param reader The reader to read from.
|
||||
*
|
||||
* @param dstBuffer The buffer to read into.
|
||||
*
|
||||
* @param byteCount The number of bytes to read.
|
||||
*
|
||||
* @return The number of bytes actually read.
|
||||
*/
|
||||
int ksfu_readBufferedReader(KSBufferedReader* reader, char* dstBuffer, int byteCount);
|
||||
|
||||
/** Read from a buffered reader until the specified character is encountered.
|
||||
* All bytes up to and including the character will be read.
|
||||
*
|
||||
* @param reader The reader to read from.
|
||||
*
|
||||
* @param ch The character to look for.
|
||||
*
|
||||
* @param dstBuffer The buffer to read into.
|
||||
*
|
||||
* @param length in: The maximum number of bytes to read before giving up the search.
|
||||
* out: The actual number of bytes read.
|
||||
*
|
||||
* @return True if the character was found before giving up.
|
||||
*/
|
||||
bool ksfu_readBufferedReaderUntilChar(KSBufferedReader* reader, int ch, char* dstBuffer, int* length);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSFileUtils_h
|
||||
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// KSHTTPMultipartPostBody.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-19.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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/Foundation.h>
|
||||
|
||||
|
||||
/**
|
||||
* Builds a multipart MIME HTTP body.
|
||||
*/
|
||||
@interface KSHTTPMultipartPostBody: NSObject
|
||||
|
||||
/** The content-type identifier for this body. */
|
||||
@property(nonatomic,readonly,retain) NSString* contentType;
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* @return A new body.
|
||||
*/
|
||||
+ (KSHTTPMultipartPostBody*) body;
|
||||
|
||||
/** This body's data, encoded for sending in an HTTP request. */
|
||||
- (NSData*) data;
|
||||
|
||||
/** Append a new data field to the body.
|
||||
*
|
||||
* @param data The data to append.
|
||||
*
|
||||
* @param name The field name.
|
||||
*
|
||||
* @param contentType The field's content-type (nil = omit).
|
||||
*
|
||||
* @param filename The field's filename (nil = omit).
|
||||
*/
|
||||
- (void) appendData:(NSData*) data
|
||||
name:(NSString*) name
|
||||
contentType:(NSString*) contentType
|
||||
filename:(NSString*) filename;
|
||||
|
||||
/** Append a new UTF-8 encoded string field to the body.
|
||||
*
|
||||
* @param string The string to append.
|
||||
*
|
||||
* @param name The field name.
|
||||
*
|
||||
* @param contentType The field's content-type (nil = omit).
|
||||
*
|
||||
* @param filename The field's filename (nil = omit).
|
||||
*/
|
||||
- (void) appendUTF8String:(NSString*) string
|
||||
name:(NSString*) name
|
||||
contentType:(NSString*) contentType
|
||||
filename:(NSString*) filename;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// KSHTTPRequestSender.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-19.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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/Foundation.h>
|
||||
|
||||
|
||||
/**
|
||||
* Sends HTTP requests via the global dispatch queue, informing the caller of
|
||||
* success, failure, or errors via blocks.
|
||||
*/
|
||||
@interface KSHTTPRequestSender : NSObject
|
||||
|
||||
/** Constructor.
|
||||
*/
|
||||
+ (KSHTTPRequestSender*) sender;
|
||||
|
||||
/** Send an HTTP request.
|
||||
* The request gets sent via the global dispatch queue using default priority.
|
||||
* Result blocks will be invoked on the main thread.
|
||||
*
|
||||
* @param request The request to send.
|
||||
*
|
||||
* @param successBlock Gets executed when the request completes successfully.
|
||||
*
|
||||
* @param failureBlock Gets executed if the request fails or receives an HTTP
|
||||
* response indicating failure.
|
||||
*
|
||||
* @param errorBlock Gets executed if an error prevents the request from being
|
||||
* sent or an invalid (non-HTTP) response is received.
|
||||
*/
|
||||
- (void) sendRequest:(NSURLRequest*) request
|
||||
onSuccess:(void(^)(NSHTTPURLResponse* response, NSData* data)) successBlock
|
||||
onFailure:(void(^)(NSHTTPURLResponse* response, NSData* data)) failureBlock
|
||||
onError:(void(^)(NSError* error)) errorBlock;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,562 @@
|
||||
//
|
||||
// KSJSONCodec.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-01-07.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/* Reads and writes JSON encoded data.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_KSJSONCodec_h
|
||||
#define HDR_KSJSONCodec_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Tells the encoder to automatically determine the length of a field value.
|
||||
* Currently, this is done using strlen().
|
||||
*/
|
||||
#define KSJSON_SIZE_AUTOMATIC -1
|
||||
|
||||
enum
|
||||
{
|
||||
/** Encoding or decoding: Everything completed without error */
|
||||
KSJSON_OK = 0,
|
||||
|
||||
/** Encoding or decoding: Encountered an unexpected or invalid character */
|
||||
KSJSON_ERROR_INVALID_CHARACTER = 1,
|
||||
|
||||
/** Decoding: Source data was too long. */
|
||||
KSJSON_ERROR_DATA_TOO_LONG = 2,
|
||||
|
||||
/** Encoding: addJSONData could not handle the data.
|
||||
* This code is not used by the decoder, but is meant to be returned by
|
||||
* the addJSONData callback method if it couldn't handle the data.
|
||||
*/
|
||||
KSJSON_ERROR_CANNOT_ADD_DATA = 3,
|
||||
|
||||
/** Decoding: Source data appears to be truncated. */
|
||||
KSJSON_ERROR_INCOMPLETE = 4,
|
||||
|
||||
/** Decoding: Parsing failed due to bad data structure/type/contents.
|
||||
* This code is not used by the decoder, but is meant to be returned
|
||||
* by the user callback methods if the decoded data is incorrect for
|
||||
* semantic or structural reasons.
|
||||
*/
|
||||
KSJSON_ERROR_INVALID_DATA = 5,
|
||||
};
|
||||
|
||||
/** Get a description for an error code.
|
||||
*
|
||||
* @param error The error code.
|
||||
*
|
||||
* @return A string describing the error.
|
||||
*/
|
||||
const char* ksjson_stringForError(const int error);
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Encode
|
||||
// ============================================================================
|
||||
|
||||
/** Function pointer for adding more UTF-8 encoded JSON data.
|
||||
*
|
||||
* @param data The UTF-8 data to add.
|
||||
*
|
||||
* @param length The length of the data.
|
||||
*
|
||||
* @param userData user-specified contextual data.
|
||||
*
|
||||
* @return KSJSON_OK if the data was handled.
|
||||
* otherwise KSJSON_ERROR_CANNOT_ADD_DATA.
|
||||
*/
|
||||
typedef int (*KSJSONAddDataFunc)(const char* data, int length, void* userData);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/** Function to call to add more encoded JSON data. */
|
||||
KSJSONAddDataFunc addJSONData;
|
||||
|
||||
/** User-specified data */
|
||||
void* userData;
|
||||
|
||||
/** How many containers deep we are. */
|
||||
int containerLevel;
|
||||
|
||||
/** Whether or not the current container is an object. */
|
||||
bool isObject[200];
|
||||
|
||||
/** true if this is the first entry at the current container level. */
|
||||
bool containerFirstEntry;
|
||||
|
||||
bool prettyPrint;
|
||||
|
||||
} KSJSONEncodeContext;
|
||||
|
||||
|
||||
/** Begin a new encoding process.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param prettyPrint If true, insert whitespace to make the output pretty.
|
||||
*
|
||||
* @param addJSONData Function to handle adding data.
|
||||
*
|
||||
* @param userData User-specified data which gets passed to addJSONData.
|
||||
*/
|
||||
void ksjson_beginEncode(KSJSONEncodeContext* context,
|
||||
bool prettyPrint,
|
||||
KSJSONAddDataFunc addJSONData,
|
||||
void* userData);
|
||||
|
||||
/** End the encoding process, ending any remaining open containers.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_endEncode(KSJSONEncodeContext* context);
|
||||
|
||||
/** Add a boolean element.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param name The element's name.
|
||||
*
|
||||
* @param value The element's value.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_addBooleanElement(KSJSONEncodeContext* context,
|
||||
const char* name,
|
||||
bool value);
|
||||
|
||||
/** Add an integer element.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param name The element's name.
|
||||
*
|
||||
* @param value The element's value.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_addIntegerElement(KSJSONEncodeContext* context,
|
||||
const char* name,
|
||||
int64_t value);
|
||||
|
||||
/** Add an unsigned integer element.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param name The element's name.
|
||||
*
|
||||
* @param value The element's value.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_addUIntegerElement(KSJSONEncodeContext* const context,
|
||||
const char* const name,
|
||||
uint64_t value);
|
||||
|
||||
/** Add a floating point element.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param name The element's name.
|
||||
*
|
||||
* @param value The element's value.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_addFloatingPointElement(KSJSONEncodeContext* context,
|
||||
const char* name,
|
||||
double value);
|
||||
|
||||
/** Add a null element.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param name The element's name.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_addNullElement(KSJSONEncodeContext* context,
|
||||
const char* name);
|
||||
|
||||
/** Add a string element.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param name The element's name.
|
||||
*
|
||||
* @param value The element's value.
|
||||
*
|
||||
* @param length the length of the string, or KSJSON_SIZE_AUTOMATIC.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_addStringElement(KSJSONEncodeContext* context,
|
||||
const char* name,
|
||||
const char* value,
|
||||
int length);
|
||||
|
||||
/** Start an incrementally-built string element.
|
||||
*
|
||||
* Use this for constructing very large strings.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param name The element's name.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_beginStringElement(KSJSONEncodeContext* context,
|
||||
const char* name);
|
||||
|
||||
/** Add a string fragment to an incrementally-built string element.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param value The string fragment.
|
||||
*
|
||||
* @param length the length of the string fragment.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_appendStringElement(KSJSONEncodeContext* context,
|
||||
const char* value,
|
||||
int length);
|
||||
|
||||
/** End an incrementally-built string element.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_endStringElement(KSJSONEncodeContext* context);
|
||||
|
||||
/** Add a string element. The element will be converted to string-coded hex.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param name The element's name.
|
||||
*
|
||||
* @param value The element's value.
|
||||
*
|
||||
* @param length The length of the data.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_addDataElement(KSJSONEncodeContext* const context,
|
||||
const char* name,
|
||||
const char* value,
|
||||
int length);
|
||||
|
||||
/** Start an incrementally-built data element. The element will be converted
|
||||
* to string-coded hex.
|
||||
*
|
||||
* Use this for constructing very large data elements.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param name The element's name.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_beginDataElement(KSJSONEncodeContext* const context,
|
||||
const char* const name);
|
||||
|
||||
/** Add a data fragment to an incrementally-built data element.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param value The data fragment.
|
||||
*
|
||||
* @param length the length of the data fragment.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_appendDataElement(KSJSONEncodeContext* const context,
|
||||
const char* const value,
|
||||
int length);
|
||||
|
||||
/** End an incrementally-built data element.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_endDataElement(KSJSONEncodeContext* const context);
|
||||
|
||||
/** Add a pre-formatted JSON element.
|
||||
*
|
||||
* @param encodeContext The encoding context.
|
||||
*
|
||||
* @param name The element's name.
|
||||
*
|
||||
* @param jsonData The element's value. MUST BE VALID JSON!
|
||||
*
|
||||
* @param jsonDataLength The length of the element.
|
||||
*
|
||||
* @param closeLastContainer If false, do not close the last container.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_addJSONElement(KSJSONEncodeContext* const encodeContext,
|
||||
const char* restrict const name,
|
||||
const char* restrict const jsonData,
|
||||
const int jsonDataLength,
|
||||
const bool closeLastContainer);
|
||||
|
||||
/** Begin a new object container.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param name The object's name.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_beginObject(KSJSONEncodeContext* context,
|
||||
const char* name);
|
||||
|
||||
/** Begin a new array container.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param name The array's name.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_beginArray(KSJSONEncodeContext* context,
|
||||
const char* name);
|
||||
|
||||
/** Begin a generic JSON element, adding any necessary JSON preamble text,
|
||||
* including commas and names.
|
||||
* Note: This does not add any object or array specifiers ('{', '[').
|
||||
*
|
||||
* @param context The JSON context.
|
||||
*
|
||||
* @param name The name of the next element (only needed if parent is a dictionary).
|
||||
*/
|
||||
int ksjson_beginElement(KSJSONEncodeContext* const context,
|
||||
const char* const name);
|
||||
|
||||
/** Add JSON data manually.
|
||||
* This function just passes your data directly through, even if it's malforned.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param data The data to write.
|
||||
*
|
||||
* @param length The length of the data.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_addRawJSONData(KSJSONEncodeContext* const context,
|
||||
const char* const data,
|
||||
const int length);
|
||||
|
||||
/** End the current container and return to the next higher level.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @return KSJSON_OK if the process was successful.
|
||||
*/
|
||||
int ksjson_endContainer(KSJSONEncodeContext* context);
|
||||
|
||||
/** Decode and add JSON data from a file.
|
||||
*
|
||||
* @param context The encoding context.
|
||||
*
|
||||
* @param name The name to give the top element from the file.
|
||||
*
|
||||
* @param filename The file to read from.
|
||||
*
|
||||
* @param closeLastContainer If false, do not close the last container.
|
||||
*/
|
||||
int ksjson_addJSONFromFile(KSJSONEncodeContext* const context,
|
||||
const char* restrict const name,
|
||||
const char* restrict const filename,
|
||||
const bool closeLastContainer);
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Decode
|
||||
// ============================================================================
|
||||
|
||||
|
||||
/**
|
||||
* Callbacks called during a JSON decode process.
|
||||
* All function pointers must point to valid functions.
|
||||
*/
|
||||
typedef struct KSJSONDecodeCallbacks
|
||||
{
|
||||
/** Called when a boolean element is decoded.
|
||||
*
|
||||
* @param name The element's name.
|
||||
*
|
||||
* @param value The element's value.
|
||||
*
|
||||
* @param userData Data that was specified when calling ksjson_decode().
|
||||
*
|
||||
* @return KSJSON_OK if decoding should continue.
|
||||
*/
|
||||
int (*onBooleanElement)(const char* name,
|
||||
bool value,
|
||||
void* userData);
|
||||
|
||||
/** Called when a floating point element is decoded.
|
||||
*
|
||||
* @param name The element's name.
|
||||
*
|
||||
* @param value The element's value.
|
||||
*
|
||||
* @param userData Data that was specified when calling ksjson_decode().
|
||||
*
|
||||
* @return KSJSON_OK if decoding should continue.
|
||||
*/
|
||||
int (*onFloatingPointElement)(const char* name,
|
||||
double value,
|
||||
void* userData);
|
||||
|
||||
/** Called when an integer element is decoded.
|
||||
*
|
||||
* @param name The element's name.
|
||||
*
|
||||
* @param value The element's value.
|
||||
*
|
||||
* @param userData Data that was specified when calling ksjson_decode().
|
||||
*
|
||||
* @return KSJSON_OK if decoding should continue.
|
||||
*/
|
||||
int (*onIntegerElement)(const char* name,
|
||||
int64_t value,
|
||||
void* userData);
|
||||
|
||||
/** Called when a null element is decoded.
|
||||
*
|
||||
* @param name The element's name.
|
||||
*
|
||||
* @param userData Data that was specified when calling ksjson_decode().
|
||||
*
|
||||
* @return KSJSON_OK if decoding should continue.
|
||||
*/
|
||||
int (*onNullElement)(const char* name,
|
||||
void* userData);
|
||||
|
||||
/** Called when a string element is decoded.
|
||||
*
|
||||
* @param name The element's name.
|
||||
*
|
||||
* @param value The element's value.
|
||||
*
|
||||
* @param userData Data that was specified when calling ksjson_decode().
|
||||
*
|
||||
* @return KSJSON_OK if decoding should continue.
|
||||
*/
|
||||
int (*onStringElement)(const char* name,
|
||||
const char* value,
|
||||
void* userData);
|
||||
|
||||
/** Called when a new object is encountered.
|
||||
*
|
||||
* @param name The object's name.
|
||||
*
|
||||
* @param userData Data that was specified when calling ksjson_decode().
|
||||
*
|
||||
* @return KSJSON_OK if decoding should continue.
|
||||
*/
|
||||
int (*onBeginObject)(const char* name,
|
||||
void* userData);
|
||||
|
||||
/** Called when a new array is encountered.
|
||||
*
|
||||
* @param name The array's name.
|
||||
*
|
||||
* @param userData Data that was specified when calling ksjson_decode().
|
||||
*
|
||||
* @return KSJSON_OK if decoding should continue.
|
||||
*/
|
||||
int (*onBeginArray)(const char* name,
|
||||
void* userData);
|
||||
|
||||
/** Called when leaving the current container and returning to the next
|
||||
* higher level container.
|
||||
*
|
||||
* @param userData Data that was specified when calling ksjson_decode().
|
||||
*
|
||||
* @return KSJSON_OK if decoding should continue.
|
||||
*/
|
||||
int (*onEndContainer)(void* userData);
|
||||
|
||||
/** Called when the end of the input data is reached.
|
||||
*
|
||||
* @param userData Data that was specified when calling ksjson_decode().
|
||||
*
|
||||
* @return KSJSON_OK if decoding should continue.
|
||||
*/
|
||||
int (*onEndData)(void* userData);
|
||||
|
||||
} KSJSONDecodeCallbacks;
|
||||
|
||||
|
||||
/** Read a JSON encoded file from the specified FD.
|
||||
*
|
||||
* @param data UTF-8 encoded JSON data.
|
||||
*
|
||||
* @param length Length of the data.
|
||||
*
|
||||
* @param stringBuffer A buffer to use for decoding strings.
|
||||
* Note: 1/4 of this buffer will be used for dictionary name decoding.
|
||||
*
|
||||
* @param stringBufferLength The length of the string buffer.
|
||||
*
|
||||
* @param callbacks The callbacks to call while decoding.
|
||||
*
|
||||
* @param userData Any data you would like passed to the callbacks.
|
||||
*
|
||||
* @oaram errorOffset If not null, will contain the offset into the data
|
||||
* where the error (if any) occurred.
|
||||
*
|
||||
* @return KSJSON_OK if succesful. An error code otherwise.
|
||||
*/
|
||||
int ksjson_decode(const char* data,
|
||||
int length,
|
||||
char* stringBuffer,
|
||||
int stringBufferLength,
|
||||
KSJSONDecodeCallbacks* callbacks,
|
||||
void* userData,
|
||||
int* errorOffset);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSJSONCodec_h
|
||||
@@ -0,0 +1,390 @@
|
||||
//
|
||||
// KSLogger.h
|
||||
//
|
||||
// Created by Karl Stenerud on 11-06-25.
|
||||
//
|
||||
// Copyright (c) 2011 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/**
|
||||
* KSLogger
|
||||
* ========
|
||||
*
|
||||
* Prints log entries to the console consisting of:
|
||||
* - Level (Error, Warn, Info, Debug, Trace)
|
||||
* - File
|
||||
* - Line
|
||||
* - Function
|
||||
* - Message
|
||||
*
|
||||
* Allows setting the minimum logging level in the preprocessor.
|
||||
*
|
||||
* Works in C or Objective-C contexts, with or without ARC, using CLANG or GCC.
|
||||
*
|
||||
*
|
||||
* =====
|
||||
* USAGE
|
||||
* =====
|
||||
*
|
||||
* Set the log level in your "Preprocessor Macros" build setting. You may choose
|
||||
* TRACE, DEBUG, INFO, WARN, ERROR. If nothing is set, it defaults to ERROR.
|
||||
*
|
||||
* Example: KSLogger_Level=WARN
|
||||
*
|
||||
* Anything below the level specified for KSLogger_Level will not be compiled
|
||||
* or printed.
|
||||
*
|
||||
*
|
||||
* Next, include the header file:
|
||||
*
|
||||
* #include "KSLogger.h"
|
||||
*
|
||||
*
|
||||
* Next, call the logger functions from your code (using objective-c strings
|
||||
* in objective-C files and regular strings in regular C files):
|
||||
*
|
||||
* Code:
|
||||
* KSLOG_ERROR(@"Some error message");
|
||||
*
|
||||
* Prints:
|
||||
* 2011-07-16 05:41:01.379 TestApp[4439:f803] ERROR: SomeClass.m (21): -[SomeFunction]: Some error message
|
||||
*
|
||||
* Code:
|
||||
* KSLOG_INFO(@"Info about %@", someObject);
|
||||
*
|
||||
* Prints:
|
||||
* 2011-07-16 05:44:05.239 TestApp[4473:f803] INFO : SomeClass.m (20): -[SomeFunction]: Info about <NSObject: 0xb622840>
|
||||
*
|
||||
*
|
||||
* The "BASIC" versions of the macros behave exactly like NSLog() or printf(),
|
||||
* except they respect the KSLogger_Level setting:
|
||||
*
|
||||
* Code:
|
||||
* KSLOGBASIC_ERROR(@"A basic log entry");
|
||||
*
|
||||
* Prints:
|
||||
* 2011-07-16 05:44:05.916 TestApp[4473:f803] A basic log entry
|
||||
*
|
||||
*
|
||||
* NOTE: In C files, use "" instead of @"" in the format field. Logging calls
|
||||
* in C files do not print the NSLog preamble:
|
||||
*
|
||||
* Objective-C version:
|
||||
* KSLOG_ERROR(@"Some error message");
|
||||
*
|
||||
* 2011-07-16 05:41:01.379 TestApp[4439:f803] ERROR: SomeClass.m (21): -[SomeFunction]: Some error message
|
||||
*
|
||||
* C version:
|
||||
* KSLOG_ERROR("Some error message");
|
||||
*
|
||||
* ERROR: SomeClass.c (21): SomeFunction(): Some error message
|
||||
*
|
||||
*
|
||||
* =============
|
||||
* LOCAL LOGGING
|
||||
* =============
|
||||
*
|
||||
* You can control logging messages at the local file level using the
|
||||
* "KSLogger_LocalLevel" define. Note that it must be defined BEFORE
|
||||
* including KSLogger.h
|
||||
*
|
||||
* The KSLOG_XX() and KSLOGBASIC_XX() macros will print out based on the LOWER
|
||||
* of KSLogger_Level and KSLogger_LocalLevel, so if KSLogger_Level is DEBUG
|
||||
* and KSLogger_LocalLevel is TRACE, it will print all the way down to the trace
|
||||
* level for the local file where KSLogger_LocalLevel was defined, and to the
|
||||
* debug level everywhere else.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* // KSLogger_LocalLevel, if defined, MUST come BEFORE including KSLogger.h
|
||||
* #define KSLogger_LocalLevel TRACE
|
||||
* #import "KSLogger.h"
|
||||
*
|
||||
*
|
||||
* ===============
|
||||
* IMPORTANT NOTES
|
||||
* ===============
|
||||
*
|
||||
* The C logger changes its behavior depending on the value of the preprocessor
|
||||
* define KSLogger_CBufferSize.
|
||||
*
|
||||
* If KSLogger_CBufferSize is > 0, the C logger will behave in an async-safe
|
||||
* manner, calling write() instead of printf(). Any log messages that exceed the
|
||||
* length specified by KSLogger_CBufferSize will be truncated.
|
||||
*
|
||||
* If KSLogger_CBufferSize == 0, the C logger will use printf(), and there will
|
||||
* be no limit on the log message length.
|
||||
*
|
||||
* KSLogger_CBufferSize can only be set as a preprocessor define, and will
|
||||
* default to 1024 if not specified during compilation.
|
||||
*/
|
||||
|
||||
|
||||
// ============================================================================
|
||||
#pragma mark - (internal) -
|
||||
// ============================================================================
|
||||
|
||||
|
||||
#ifndef HDR_KSLogger_h
|
||||
#define HDR_KSLogger_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
#ifdef __OBJC__
|
||||
|
||||
#import <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
void i_kslog_logObjC(const char* level,
|
||||
const char* file,
|
||||
int line,
|
||||
const char* function,
|
||||
CFStringRef fmt, ...);
|
||||
|
||||
void i_kslog_logObjCBasic(CFStringRef fmt, ...);
|
||||
|
||||
#define i_KSLOG_FULL(LEVEL,FILE,LINE,FUNCTION,FMT,...) i_kslog_logObjC(LEVEL,FILE,LINE,FUNCTION,(__bridge CFStringRef)FMT,##__VA_ARGS__)
|
||||
#define i_KSLOG_BASIC(FMT, ...) i_kslog_logObjCBasic((__bridge CFStringRef)FMT,##__VA_ARGS__)
|
||||
|
||||
#else // __OBJC__
|
||||
|
||||
void i_kslog_logC(const char* level,
|
||||
const char* file,
|
||||
int line,
|
||||
const char* function,
|
||||
const char* fmt, ...);
|
||||
|
||||
void i_kslog_logCBasic(const char* fmt, ...);
|
||||
|
||||
#define i_KSLOG_FULL i_kslog_logC
|
||||
#define i_KSLOG_BASIC i_kslog_logCBasic
|
||||
|
||||
#endif // __OBJC__
|
||||
|
||||
|
||||
/* Back up any existing defines by the same name */
|
||||
#ifdef KS_NONE
|
||||
#define KSLOG_BAK_NONE KS_NONE
|
||||
#undef KS_NONE
|
||||
#endif
|
||||
#ifdef ERROR
|
||||
#define KSLOG_BAK_ERROR ERROR
|
||||
#undef ERROR
|
||||
#endif
|
||||
#ifdef WARN
|
||||
#define KSLOG_BAK_WARN WARN
|
||||
#undef WARN
|
||||
#endif
|
||||
#ifdef INFO
|
||||
#define KSLOG_BAK_INFO INFO
|
||||
#undef INFO
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
#define KSLOG_BAK_DEBUG DEBUG
|
||||
#undef DEBUG
|
||||
#endif
|
||||
#ifdef TRACE
|
||||
#define KSLOG_BAK_TRACE TRACE
|
||||
#undef TRACE
|
||||
#endif
|
||||
|
||||
|
||||
#define KSLogger_Level_None 0
|
||||
#define KSLogger_Level_Error 10
|
||||
#define KSLogger_Level_Warn 20
|
||||
#define KSLogger_Level_Info 30
|
||||
#define KSLogger_Level_Debug 40
|
||||
#define KSLogger_Level_Trace 50
|
||||
|
||||
#define KS_NONE KSLogger_Level_None
|
||||
#define ERROR KSLogger_Level_Error
|
||||
#define WARN KSLogger_Level_Warn
|
||||
#define INFO KSLogger_Level_Info
|
||||
#define DEBUG KSLogger_Level_Debug
|
||||
#define TRACE KSLogger_Level_Trace
|
||||
|
||||
|
||||
#ifndef KSLogger_Level
|
||||
#define KSLogger_Level KSLogger_Level_Error
|
||||
#endif
|
||||
|
||||
#ifndef KSLogger_LocalLevel
|
||||
#define KSLogger_LocalLevel KSLogger_Level_None
|
||||
#endif
|
||||
|
||||
#define a_KSLOG_FULL(LEVEL, FMT, ...) \
|
||||
i_KSLOG_FULL(LEVEL, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
__PRETTY_FUNCTION__, \
|
||||
FMT, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
|
||||
|
||||
// ============================================================================
|
||||
#pragma mark - API -
|
||||
// ============================================================================
|
||||
|
||||
/** Set the filename to log to.
|
||||
*
|
||||
* @param filename The file to write to (NULL = write to stdout).
|
||||
*
|
||||
* @param overwrite If true, overwrite the log file.
|
||||
*/
|
||||
bool kslog_setLogFilename(const char* filename, bool overwrite);
|
||||
|
||||
/** Clear the log file. */
|
||||
bool kslog_clearLogFile(void);
|
||||
|
||||
/** Tests if the logger would print at the specified level.
|
||||
*
|
||||
* @param LEVEL The level to test for. One of:
|
||||
* KSLogger_Level_Error,
|
||||
* KSLogger_Level_Warn,
|
||||
* KSLogger_Level_Info,
|
||||
* KSLogger_Level_Debug,
|
||||
* KSLogger_Level_Trace,
|
||||
*
|
||||
* @return TRUE if the logger would print at the specified level.
|
||||
*/
|
||||
#define KSLOG_PRINTS_AT_LEVEL(LEVEL) \
|
||||
(KSLogger_Level >= LEVEL || KSLogger_LocalLevel >= LEVEL)
|
||||
|
||||
/** Log a message regardless of the log settings.
|
||||
* Normal version prints out full context. Basic version prints directly.
|
||||
*
|
||||
* @param FMT The format specifier, followed by its arguments.
|
||||
*/
|
||||
#define KSLOG_ALWAYS(FMT, ...) a_KSLOG_FULL("FORCE", FMT, ##__VA_ARGS__)
|
||||
#define KSLOGBASIC_ALWAYS(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
|
||||
|
||||
|
||||
/** Log an error.
|
||||
* Normal version prints out full context. Basic version prints directly.
|
||||
*
|
||||
* @param FMT The format specifier, followed by its arguments.
|
||||
*/
|
||||
#if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Error)
|
||||
#define KSLOG_ERROR(FMT, ...) a_KSLOG_FULL("ERROR", FMT, ##__VA_ARGS__)
|
||||
#define KSLOGBASIC_ERROR(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
|
||||
#else
|
||||
#define KSLOG_ERROR(FMT, ...)
|
||||
#define KSLOGBASIC_ERROR(FMT, ...)
|
||||
#endif
|
||||
|
||||
/** Log a warning.
|
||||
* Normal version prints out full context. Basic version prints directly.
|
||||
*
|
||||
* @param FMT The format specifier, followed by its arguments.
|
||||
*/
|
||||
#if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Warn)
|
||||
#define KSLOG_WARN(FMT, ...) a_KSLOG_FULL("WARN ", FMT, ##__VA_ARGS__)
|
||||
#define KSLOGBASIC_WARN(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
|
||||
#else
|
||||
#define KSLOG_WARN(FMT, ...)
|
||||
#define KSLOGBASIC_WARN(FMT, ...)
|
||||
#endif
|
||||
|
||||
/** Log an info message.
|
||||
* Normal version prints out full context. Basic version prints directly.
|
||||
*
|
||||
* @param FMT The format specifier, followed by its arguments.
|
||||
*/
|
||||
#if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Info)
|
||||
#define KSLOG_INFO(FMT, ...) a_KSLOG_FULL("INFO ", FMT, ##__VA_ARGS__)
|
||||
#define KSLOGBASIC_INFO(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
|
||||
#else
|
||||
#define KSLOG_INFO(FMT, ...)
|
||||
#define KSLOGBASIC_INFO(FMT, ...)
|
||||
#endif
|
||||
|
||||
/** Log a debug message.
|
||||
* Normal version prints out full context. Basic version prints directly.
|
||||
*
|
||||
* @param FMT The format specifier, followed by its arguments.
|
||||
*/
|
||||
#if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Debug)
|
||||
#define KSLOG_DEBUG(FMT, ...) a_KSLOG_FULL("DEBUG", FMT, ##__VA_ARGS__)
|
||||
#define KSLOGBASIC_DEBUG(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
|
||||
#else
|
||||
#define KSLOG_DEBUG(FMT, ...)
|
||||
#define KSLOGBASIC_DEBUG(FMT, ...)
|
||||
#endif
|
||||
|
||||
/** Log a trace message.
|
||||
* Normal version prints out full context. Basic version prints directly.
|
||||
*
|
||||
* @param FMT The format specifier, followed by its arguments.
|
||||
*/
|
||||
#if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Trace)
|
||||
#define KSLOG_TRACE(FMT, ...) a_KSLOG_FULL("TRACE", FMT, ##__VA_ARGS__)
|
||||
#define KSLOGBASIC_TRACE(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
|
||||
#else
|
||||
#define KSLOG_TRACE(FMT, ...)
|
||||
#define KSLOGBASIC_TRACE(FMT, ...)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// ============================================================================
|
||||
#pragma mark - (internal) -
|
||||
// ============================================================================
|
||||
|
||||
/* Put everything back to the way we found it. */
|
||||
#undef ERROR
|
||||
#ifdef KSLOG_BAK_ERROR
|
||||
#define ERROR KSLOG_BAK_ERROR
|
||||
#undef KSLOG_BAK_ERROR
|
||||
#endif
|
||||
#undef WARNING
|
||||
#ifdef KSLOG_BAK_WARN
|
||||
#define WARNING KSLOG_BAK_WARN
|
||||
#undef KSLOG_BAK_WARN
|
||||
#endif
|
||||
#undef INFO
|
||||
#ifdef KSLOG_BAK_INFO
|
||||
#define INFO KSLOG_BAK_INFO
|
||||
#undef KSLOG_BAK_INFO
|
||||
#endif
|
||||
#undef DEBUG
|
||||
#ifdef KSLOG_BAK_DEBUG
|
||||
#define DEBUG KSLOG_BAK_DEBUG
|
||||
#undef KSLOG_BAK_DEBUG
|
||||
#endif
|
||||
#undef TRACE
|
||||
#ifdef KSLOG_BAK_TRACE
|
||||
#define TRACE KSLOG_BAK_TRACE
|
||||
#undef KSLOG_BAK_TRACE
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSLogger_h
|
||||
@@ -0,0 +1,91 @@
|
||||
//
|
||||
// KSMemory.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-01-29.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/* Utility functions for querying the mach kernel.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_ksmemory_h
|
||||
#define HDR_ksmemory_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
/** Test if the specified memory is safe to read from.
|
||||
*
|
||||
* @param memory A pointer to the memory to test.
|
||||
* @param byteCount The number of bytes to test.
|
||||
*
|
||||
* @return True if the memory can be safely read.
|
||||
*/
|
||||
bool ksmem_isMemoryReadable(const void* const memory, const int byteCount);
|
||||
|
||||
/** Test how much memory is readable from the specified pointer.
|
||||
*
|
||||
* @param memory A pointer to the memory to test.
|
||||
* @param tryByteCount The number of bytes to test.
|
||||
*
|
||||
* @return The number of bytes that are readable from that address.
|
||||
*/
|
||||
int ksmem_maxReadableBytes(const void* const memory, const int tryByteCount);
|
||||
|
||||
/** Copy memory safely. If the memory is not accessible, returns false
|
||||
* rather than crashing.
|
||||
*
|
||||
* @param src The source location to copy from.
|
||||
*
|
||||
* @param dst The location to copy to.
|
||||
*
|
||||
* @param byteCount The number of bytes to copy.
|
||||
*
|
||||
* @return true if successful.
|
||||
*/
|
||||
bool ksmem_copySafely(const void* restrict const src, void* restrict const dst, int byteCount);
|
||||
|
||||
/** Copies up to numBytes of data from src to dest, stopping if memory
|
||||
* becomes inaccessible.
|
||||
*
|
||||
* @param src The source location to copy from.
|
||||
*
|
||||
* @param dst The location to copy to.
|
||||
*
|
||||
* @param byteCount The number of bytes to copy.
|
||||
*
|
||||
* @return The number of bytes actually copied.
|
||||
*/
|
||||
int ksmem_copyMaxPossible(const void* restrict const src, void* restrict const dst, int byteCount);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_ksmemory_h
|
||||
@@ -0,0 +1,402 @@
|
||||
//
|
||||
// KSObjC.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-08-30.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
#ifndef HDR_KSObjC_h
|
||||
#define HDR_KSObjC_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KSObjCTypeUnknown = 0,
|
||||
KSObjCTypeClass,
|
||||
KSObjCTypeObject,
|
||||
KSObjCTypeBlock,
|
||||
} KSObjCType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KSObjCClassTypeUnknown = 0,
|
||||
KSObjCClassTypeString,
|
||||
KSObjCClassTypeDate,
|
||||
KSObjCClassTypeURL,
|
||||
KSObjCClassTypeArray,
|
||||
KSObjCClassTypeDictionary,
|
||||
KSObjCClassTypeNumber,
|
||||
KSObjCClassTypeException,
|
||||
} KSObjCClassType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* name;
|
||||
const char* type;
|
||||
int index;
|
||||
} KSObjCIvar;
|
||||
|
||||
|
||||
//======================================================================
|
||||
#pragma mark - Basic Objective-C Queries -
|
||||
//======================================================================
|
||||
|
||||
/** Check if a pointer is a tagged pointer or not.
|
||||
*
|
||||
* @param pointer The pointer to check.
|
||||
* @return true if it's a tagged pointer.
|
||||
*/
|
||||
bool ksobjc_isTaggedPointer(const void* const pointer);
|
||||
|
||||
/** Check if a pointer is a valid tagged pointer.
|
||||
*
|
||||
* @param pointer The pointer to check.
|
||||
* @return true if it's a valid tagged pointer.
|
||||
*/
|
||||
bool ksobjc_isValidTaggedPointer(const void* const pointer);
|
||||
|
||||
/** Query a pointer to see what kind of object it points to.
|
||||
* If the pointer points to a class, this method will verify that its basic
|
||||
* class data and ivars are valid,
|
||||
* If the pointer points to an object, it will verify the object data (if
|
||||
* recognized as a common class), and the isa's basic class info (everything
|
||||
* except ivars).
|
||||
*
|
||||
* Warning: In order to ensure that an object is both valid and accessible,
|
||||
* always call this method on an object or class pointer (including
|
||||
* those returned by ksobjc_isaPointer() and ksobjc_superclass())
|
||||
* BEFORE calling any other function in this module.
|
||||
*
|
||||
* @param objectOrClassPtr Pointer to something that may be an object or class.
|
||||
*
|
||||
* @return The type of object, or KSObjCTypeNone if it was not an object or
|
||||
* was inaccessible.
|
||||
*/
|
||||
KSObjCType ksobjc_objectType(const void* objectOrClassPtr);
|
||||
|
||||
/** Check that an object contains valid data.
|
||||
* If the object is of a recognized type (string, date, array, etc),
|
||||
* this function will verify that its internal data is intact.
|
||||
*
|
||||
* Call this function before calling any object-specific functions.
|
||||
*
|
||||
* @param object The object to verify.
|
||||
*
|
||||
* @return true if the object is valid.
|
||||
*/
|
||||
bool ksobjc_isValidObject(const void* object);
|
||||
|
||||
/** Fetch the isa pointer from an object or class.
|
||||
*
|
||||
* @param objectOrClassPtr Pointer to a valid object or class.
|
||||
*
|
||||
* @return The isa pointer.
|
||||
*/
|
||||
const void* ksobjc_isaPointer(const void* objectOrClassPtr);
|
||||
|
||||
/** Fetch the super class pointer from a class.
|
||||
*
|
||||
* @param classPtr Pointer to a valid class.
|
||||
*
|
||||
* @return the super class.
|
||||
*/
|
||||
const void* ksobjc_superClass(const void* classPtr);
|
||||
|
||||
/** Get the base class this class is derived from.
|
||||
* It will always return the highest level non-root class in the hierarchy
|
||||
* (one below NSObject or NSProxy), unless the passed in object or class
|
||||
* actually is a root class.
|
||||
*
|
||||
* @param classPtr Pointer to a valid class.
|
||||
*
|
||||
* @return The base class.
|
||||
*/
|
||||
const void* ksobjc_baseClass(const void* const classPtr);
|
||||
|
||||
/** Check if a class is a meta class.
|
||||
*
|
||||
* @param classPtr Pointer to a valid class.
|
||||
*
|
||||
* @return true if the class is a meta class.
|
||||
*/
|
||||
bool ksobjc_isMetaClass(const void* classPtr);
|
||||
|
||||
/** Check if a class is a root class.
|
||||
*
|
||||
* @param classPtr Pointer to a valid class.
|
||||
*
|
||||
* @return true if the class is a root class.
|
||||
*/
|
||||
bool ksobjc_isRootClass(const void* classPtr);
|
||||
|
||||
/** Get the name of a class.
|
||||
*
|
||||
* @param classPtr Pointer to a valid class.
|
||||
*
|
||||
* @return the name, or NULL if the name inaccessible.
|
||||
*/
|
||||
const char* ksobjc_className(const void* classPtr);
|
||||
|
||||
/** Get the name of an object's class.
|
||||
* This also handles tagged pointers.
|
||||
*
|
||||
* @param objectPtr Pointer to a valid object.
|
||||
*
|
||||
* @return the name, or NULL if the name is inaccessible.
|
||||
*/
|
||||
const char* ksobjc_objectClassName(const void* objectPtr);
|
||||
|
||||
/** Check if a class has a specific name.
|
||||
*
|
||||
* @param classPtr Pointer to a valid class.
|
||||
*
|
||||
* @param className The class name to compare against.
|
||||
*
|
||||
* @return true if the class has the specified name.
|
||||
*/
|
||||
bool ksobjc_isClassNamed(const void* const classPtr, const char* const className);
|
||||
|
||||
/** Check if a class is of the specified type or a subclass thereof.
|
||||
* Note: This function is considerably slower than ksobjc_baseClassName().
|
||||
*
|
||||
* @param classPtr Pointer to a valid class.
|
||||
*
|
||||
* @param className The class name to compare against.
|
||||
*
|
||||
* @return true if the class is of the specified type or a subclass of that type.
|
||||
*/
|
||||
bool ksobjc_isKindOfClass(const void* classPtr, const char* className);
|
||||
|
||||
/** Get the number of ivars registered with a class.
|
||||
*
|
||||
* @param classPtr Pointer to a valid class.
|
||||
*
|
||||
* @return The number of ivars.
|
||||
*/
|
||||
int ksobjc_ivarCount(const void* classPtr);
|
||||
|
||||
/** Get information about ivars in a class.
|
||||
*
|
||||
* @param classPtr Pointer to a valid class.
|
||||
*
|
||||
* @param dstIvars Buffer to hold ivar data.
|
||||
*
|
||||
* @param ivarsCount The number of ivars the buffer can hold.
|
||||
*
|
||||
* @return The number of ivars copied.
|
||||
*/
|
||||
int ksobjc_ivarList(const void* classPtr, KSObjCIvar* dstIvars, int ivarsCount);
|
||||
|
||||
/** Get ivar information by name/
|
||||
*
|
||||
* @param classPtr Pointer to a valid class.
|
||||
*
|
||||
* @param name The name of the ivar to get information about.
|
||||
*
|
||||
* @param dst Buffer to hold the result.
|
||||
*
|
||||
* @return true if the operation was successful.
|
||||
*/
|
||||
bool ksobjc_ivarNamed(const void* const classPtr, const char* name, KSObjCIvar* dst);
|
||||
|
||||
/** Get the value of an ivar in an object.
|
||||
*
|
||||
* @param objectPtr Pointer to a valid object.
|
||||
*
|
||||
* @param ivarIndex The index of the ivar to fetch.
|
||||
*
|
||||
* @param dst Pointer to buffer big enough to contain the data.
|
||||
*
|
||||
* @return true if the operation was successful.
|
||||
*/
|
||||
bool ksobjc_ivarValue(const void* objectPtr, int ivarIndex, void* dst);
|
||||
|
||||
/* Get the payload from a tagged pointer.
|
||||
*
|
||||
* @param objectPtr Pointer to a valid object.
|
||||
*
|
||||
* @return the payload value.
|
||||
*/
|
||||
uintptr_t ksobjc_taggedPointerPayload(const void* taggedObjectPtr);
|
||||
|
||||
/** Generate a description of an object.
|
||||
*
|
||||
* For known common object classes it will print extra information.
|
||||
* For all other objects, it will print a standard <SomeClass: 0x12345678>
|
||||
*
|
||||
* For containers, it will only print the first object in the container.
|
||||
*
|
||||
* buffer will be null terminated unless bufferLength is 0.
|
||||
* If the string doesn't fit, it will be truncated.
|
||||
*
|
||||
* @param object the object to generate a description for.
|
||||
*
|
||||
* @param buffer The buffer to copy into.
|
||||
*
|
||||
* @param bufferLength The length of the buffer.
|
||||
*
|
||||
* @return the number of bytes copied (not including null terminator).
|
||||
*/
|
||||
int ksobjc_getDescription(void* object, char* buffer, int bufferLength);
|
||||
|
||||
/** Get the class type of an object.
|
||||
* There are a number of common class types that KSObjC understamds,
|
||||
* listed in KSObjCClassType.
|
||||
*
|
||||
* @param object The object to query.
|
||||
*
|
||||
* @return The class type, or KSObjCClassTypeUnknown if it couldn't be determined.
|
||||
*/
|
||||
KSObjCClassType ksobjc_objectClassType(const void* object);
|
||||
|
||||
|
||||
//======================================================================
|
||||
#pragma mark - Object-Specific Queries -
|
||||
//======================================================================
|
||||
|
||||
/** Check if a number was stored as floating point.
|
||||
*
|
||||
* @param object The number to query.
|
||||
* @return true if the number is floating point.
|
||||
*/
|
||||
bool ksobjc_numberIsFloat(const void* object);
|
||||
|
||||
/** Get the contents of a number as a floating point value.
|
||||
*
|
||||
* @param object The number.
|
||||
* @return The value.
|
||||
*/
|
||||
double ksobjc_numberAsFloat(const void* object);
|
||||
|
||||
/** Get the contents of a number as an integer value.
|
||||
* If the number was stored as floating point, it will be
|
||||
* truncated as per C's conversion rules.
|
||||
*
|
||||
* @param object The number.
|
||||
* @return The value.
|
||||
*/
|
||||
int64_t ksobjc_numberAsInteger(const void* object);
|
||||
|
||||
/** Copy the contents of a date object.
|
||||
*
|
||||
* @param datePtr The date to copy data from.
|
||||
*
|
||||
* @return Time interval since Jan 1 2001 00:00:00 GMT.
|
||||
*/
|
||||
double ksobjc_dateContents(const void* datePtr);
|
||||
|
||||
/** Copy the contents of a URL object.
|
||||
*
|
||||
* dst will be null terminated unless maxLength is 0.
|
||||
* If the string doesn't fit, it will be truncated.
|
||||
*
|
||||
* @param nsurl The URL to copy data from.
|
||||
*
|
||||
* @param dst The destination to copy into.
|
||||
*
|
||||
* @param maxLength The size of the buffer.
|
||||
*
|
||||
* @return the number of bytes copied (not including null terminator).
|
||||
*/
|
||||
int ksobjc_copyURLContents(const void* nsurl, char* dst, int maxLength);
|
||||
|
||||
/** Get the length of a string in characters.
|
||||
*
|
||||
* @param stringPtr Pointer to a string.
|
||||
*
|
||||
* @return The length of the string.
|
||||
*/
|
||||
int ksobjc_stringLength(const void* const stringPtr);
|
||||
|
||||
/** Copy the contents of a string object.
|
||||
*
|
||||
* dst will be null terminated unless maxLength is 0.
|
||||
* If the string doesn't fit, it will be truncated.
|
||||
*
|
||||
* @param string The string to copy data from.
|
||||
*
|
||||
* @param dst The destination to copy into.
|
||||
*
|
||||
* @param maxLength The size of the buffer.
|
||||
*
|
||||
* @return the number of bytes copied (not including null terminator).
|
||||
*/
|
||||
int ksobjc_copyStringContents(const void* string, char* dst, int maxLength);
|
||||
|
||||
/** Get an NSArray's count.
|
||||
*
|
||||
* @param arrayPtr The array to get the count from.
|
||||
*
|
||||
* @return The array's count.
|
||||
*/
|
||||
int ksobjc_arrayCount(const void* arrayPtr);
|
||||
|
||||
/** Get an NSArray's contents.
|
||||
*
|
||||
* @param arrayPtr The array to get the contents of.
|
||||
*
|
||||
* @param contents Location to copy the array's contents into.
|
||||
*
|
||||
* @param count The number of objects to copy.
|
||||
*
|
||||
* @return The number of items copied.
|
||||
*/
|
||||
int ksobjc_arrayContents(const void* arrayPtr, uintptr_t* contents, int count);
|
||||
|
||||
|
||||
//======================================================================
|
||||
#pragma mark - Broken/Unimplemented Stuff -
|
||||
//======================================================================
|
||||
|
||||
/** Get the first entry from an NSDictionary.
|
||||
*
|
||||
* WARNING: This function is broken!
|
||||
*
|
||||
* @param dict The dictionary to copy from.
|
||||
*
|
||||
* @param key Location to copy the first key into.
|
||||
*
|
||||
* @param value Location to copy the first value into.
|
||||
*
|
||||
* @return true if the operation was successful.
|
||||
*/
|
||||
bool ksobjc_dictionaryFirstEntry(const void* dict, uintptr_t* key, uintptr_t* value);
|
||||
|
||||
/** UNIMPLEMENTED
|
||||
*/
|
||||
int ksobjc_dictionaryCount(const void* dict);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSObjC_h
|
||||
@@ -0,0 +1,668 @@
|
||||
//
|
||||
// KSObjCApple.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-08-30.
|
||||
//
|
||||
// Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
//
|
||||
// This file contains Original Code and/or Modifications of Original Code
|
||||
// as defined in and that are subject to the Apple Public Source License
|
||||
// Version 2.0 (the 'License'). You may not use this file except in
|
||||
// compliance with the License. Please obtain a copy of the License at
|
||||
// http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
// file.
|
||||
//
|
||||
|
||||
// This file contains structures and constants copied from Apple header
|
||||
// files, arranged for use in KSObjC.
|
||||
|
||||
#ifndef HDR_KSObjCApple_h
|
||||
#define HDR_KSObjCApple_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <objc/objc.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
|
||||
#define MAKE_LIST_T(TYPE) \
|
||||
typedef struct TYPE##_list_t { \
|
||||
uint32_t entsizeAndFlags; \
|
||||
uint32_t count; \
|
||||
TYPE##_t first; \
|
||||
} TYPE##_list_t; \
|
||||
typedef TYPE##_list_t TYPE##_array_t
|
||||
|
||||
#define OBJC_OBJECT(NAME) \
|
||||
NAME { \
|
||||
Class isa OBJC_ISA_AVAILABILITY;
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - objc4-680/runtime/objc-msg-x86_64.s -
|
||||
// and objc4-680/runtime/objc-msg-arm64.s
|
||||
// ======================================================================
|
||||
|
||||
// Use ISA_MASK_OLD before iOS 9, in and after iOS 9, use ISA_MASK
|
||||
#if __x86_64__
|
||||
# define ISA_TAG_MASK 1UL
|
||||
# define ISA_MASK 0x00007ffffffffff8UL
|
||||
#elif defined(__arm64__)
|
||||
# define ISA_TAG_MASK 1UL
|
||||
# define ISA_MASK_OLD 0x00000001fffffff8UL
|
||||
# define ISA_MASK 0x0000000ffffffff8UL
|
||||
#else
|
||||
# define ISA_TAG_MASK 0UL
|
||||
# define ISA_MASK ~1UL
|
||||
#endif
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - objc4-680/runtime/objc-config.h -
|
||||
// ======================================================================
|
||||
|
||||
// Define SUPPORT_TAGGED_POINTERS=1 to enable tagged pointer objects
|
||||
// Be sure to edit tagged pointer SPI in objc-internal.h as well.
|
||||
#if !(__LP64__)
|
||||
# define SUPPORT_TAGGED_POINTERS 0
|
||||
#else
|
||||
# define SUPPORT_TAGGED_POINTERS 1
|
||||
#endif
|
||||
|
||||
// Define SUPPORT_MSB_TAGGED_POINTERS to use the MSB
|
||||
// as the tagged pointer marker instead of the LSB.
|
||||
// Be sure to edit tagged pointer SPI in objc-internal.h as well.
|
||||
#if !SUPPORT_TAGGED_POINTERS || !TARGET_OS_IPHONE
|
||||
# define SUPPORT_MSB_TAGGED_POINTERS 0
|
||||
#else
|
||||
# define SUPPORT_MSB_TAGGED_POINTERS 1
|
||||
#endif
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - objc4-680/runtime/objc-object.h -
|
||||
// ======================================================================
|
||||
|
||||
#if SUPPORT_TAGGED_POINTERS
|
||||
|
||||
// KS: The original values wouldn't have worked. The slot shift and mask
|
||||
// were incorrect.
|
||||
#define TAG_COUNT 8
|
||||
//#define TAG_SLOT_MASK 0xf
|
||||
#define TAG_SLOT_MASK 0x07
|
||||
|
||||
#if SUPPORT_MSB_TAGGED_POINTERS
|
||||
# define TAG_MASK (1ULL<<63)
|
||||
# define TAG_SLOT_SHIFT 60
|
||||
# define TAG_PAYLOAD_LSHIFT 4
|
||||
# define TAG_PAYLOAD_RSHIFT 4
|
||||
#else
|
||||
# define TAG_MASK 1
|
||||
//# define TAG_SLOT_SHIFT 0
|
||||
# define TAG_SLOT_SHIFT 1
|
||||
# define TAG_PAYLOAD_LSHIFT 0
|
||||
# define TAG_PAYLOAD_RSHIFT 4
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - objc4-781/runtime/objc-internal.h -
|
||||
// ======================================================================
|
||||
#if __ARM_ARCH_7K__ >= 2 || (__arm64__ && !__LP64__)
|
||||
# define SUPPORT_INDEXED_ISA 1
|
||||
#else
|
||||
# define SUPPORT_INDEXED_ISA 0
|
||||
#endif
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - objc4-680/runtime/objc-internal.h -
|
||||
// ======================================================================
|
||||
|
||||
enum
|
||||
{
|
||||
OBJC_TAG_NSAtom = 0,
|
||||
OBJC_TAG_1 = 1,
|
||||
OBJC_TAG_NSString = 2,
|
||||
OBJC_TAG_NSNumber = 3,
|
||||
OBJC_TAG_NSIndexPath = 4,
|
||||
OBJC_TAG_NSManagedObjectID = 5,
|
||||
OBJC_TAG_NSDate = 6,
|
||||
OBJC_TAG_7 = 7
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - objc4-680/runtime/objc-os.h -
|
||||
// ======================================================================
|
||||
|
||||
#ifdef __LP64__
|
||||
# define WORD_SHIFT 3UL
|
||||
# define WORD_MASK 7UL
|
||||
# define WORD_BITS 64
|
||||
#else
|
||||
# define WORD_SHIFT 2UL
|
||||
# define WORD_MASK 3UL
|
||||
# define WORD_BITS 32
|
||||
#endif
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - objc4-680/runtime/runtime.h -
|
||||
// ======================================================================
|
||||
|
||||
typedef struct objc_cache *Cache;
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - objc4-680/runtime/objc-runtime-new.h -
|
||||
// ======================================================================
|
||||
|
||||
typedef struct method_t {
|
||||
SEL name;
|
||||
const char *types;
|
||||
IMP imp;
|
||||
} method_t;
|
||||
|
||||
MAKE_LIST_T(method);
|
||||
|
||||
typedef struct ivar_t {
|
||||
#if __x86_64__
|
||||
// *offset was originally 64-bit on some x86_64 platforms.
|
||||
// We read and write only 32 bits of it.
|
||||
// Some metadata provides all 64 bits. This is harmless for unsigned
|
||||
// little-endian values.
|
||||
// Some code uses all 64 bits. class_addIvar() over-allocates the
|
||||
// offset for their benefit.
|
||||
#endif
|
||||
int32_t *offset;
|
||||
const char *name;
|
||||
const char *type;
|
||||
// alignment is sometimes -1; use alignment() instead
|
||||
uint32_t alignment_raw;
|
||||
uint32_t size;
|
||||
} ivar_t;
|
||||
|
||||
MAKE_LIST_T(ivar);
|
||||
|
||||
typedef struct property_t {
|
||||
const char *name;
|
||||
const char *attributes;
|
||||
} property_t;
|
||||
|
||||
MAKE_LIST_T(property);
|
||||
|
||||
typedef struct OBJC_OBJECT(protocol_t)
|
||||
const char *mangledName;
|
||||
struct protocol_list_t *protocols;
|
||||
method_list_t *instanceMethods;
|
||||
method_list_t *classMethods;
|
||||
method_list_t *optionalInstanceMethods;
|
||||
method_list_t *optionalClassMethods;
|
||||
property_list_t *instanceProperties;
|
||||
uint32_t size; // sizeof(protocol_t)
|
||||
uint32_t flags;
|
||||
// Fields below this point are not always present on disk.
|
||||
const char **extendedMethodTypes;
|
||||
const char *_demangledName;
|
||||
} protocol_t;
|
||||
|
||||
MAKE_LIST_T(protocol);
|
||||
|
||||
// Values for class_ro_t->flags
|
||||
// These are emitted by the compiler and are part of the ABI.
|
||||
// class is a metaclass
|
||||
#define RO_META (1<<0)
|
||||
// class is a root class
|
||||
#define RO_ROOT (1<<1)
|
||||
|
||||
typedef struct class_ro_t {
|
||||
uint32_t flags;
|
||||
uint32_t instanceStart;
|
||||
uint32_t instanceSize;
|
||||
#ifdef __LP64__
|
||||
uint32_t reserved;
|
||||
#endif
|
||||
|
||||
const uint8_t * ivarLayout;
|
||||
|
||||
const char * name;
|
||||
method_list_t * baseMethodList;
|
||||
protocol_list_t * baseProtocols;
|
||||
const ivar_list_t * ivars;
|
||||
|
||||
const uint8_t * weakIvarLayout;
|
||||
property_list_t *baseProperties;
|
||||
} class_ro_t;
|
||||
|
||||
struct class_rw_ext_t {
|
||||
const class_ro_t *ro;
|
||||
method_array_t methods;
|
||||
property_array_t properties;
|
||||
protocol_array_t protocols;
|
||||
char *demangledName;
|
||||
uint32_t version;
|
||||
};
|
||||
|
||||
typedef struct class_rw_t {
|
||||
uint32_t flags;
|
||||
uint16_t witness;
|
||||
#if SUPPORT_INDEXED_ISA
|
||||
uint16_t index;
|
||||
#endif
|
||||
|
||||
uintptr_t ro_or_rw_ext;
|
||||
Class firstSubclass;
|
||||
Class nextSiblingClass;
|
||||
|
||||
} class_rw_t;
|
||||
|
||||
typedef struct class_t {
|
||||
struct class_t *isa;
|
||||
struct class_t *superclass;
|
||||
#pragma clang diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
Cache cache;
|
||||
#pragma clang diagnostic pop
|
||||
IMP *vtable;
|
||||
uintptr_t data_NEVER_USE; // class_rw_t * plus custom rr/alloc flags
|
||||
} class_t;
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - CF-1153.18/CFRuntime.h -
|
||||
// ======================================================================
|
||||
|
||||
typedef struct __CFRuntimeBase {
|
||||
uintptr_t _cfisa;
|
||||
uint8_t _cfinfo[4];
|
||||
#if __LP64__
|
||||
uint32_t _rc;
|
||||
#endif
|
||||
} CFRuntimeBase;
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - CF-1153.18/CFInternal.h -
|
||||
// ======================================================================
|
||||
|
||||
#if defined(__BIG_ENDIAN__)
|
||||
#define __CF_BIG_ENDIAN__ 1
|
||||
#define __CF_LITTLE_ENDIAN__ 0
|
||||
#endif
|
||||
|
||||
#if defined(__LITTLE_ENDIAN__)
|
||||
#define __CF_LITTLE_ENDIAN__ 1
|
||||
#define __CF_BIG_ENDIAN__ 0
|
||||
#endif
|
||||
|
||||
#define CF_INFO_BITS (!!(__CF_BIG_ENDIAN__) * 3)
|
||||
#define CF_RC_BITS (!!(__CF_LITTLE_ENDIAN__) * 3)
|
||||
|
||||
/* Bit manipulation macros */
|
||||
/* Bits are numbered from 31 on left to 0 on right */
|
||||
/* May or may not work if you use them on bitfields in types other than UInt32, bitfields the full width of a UInt32, or anything else for which they were not designed. */
|
||||
/* In the following, N1 and N2 specify an inclusive range N2..N1 with N1 >= N2 */
|
||||
#define __CFBitfieldMask(N1, N2) ((((UInt32)~0UL) << (31UL - (N1) + (N2))) >> (31UL - N1))
|
||||
#define __CFBitfieldGetValue(V, N1, N2) (((V) & __CFBitfieldMask(N1, N2)) >> (N2))
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - CF-1153.18/CFString.c -
|
||||
// ======================================================================
|
||||
|
||||
// This is separate for C++
|
||||
struct __notInlineMutable {
|
||||
void *buffer;
|
||||
CFIndex length;
|
||||
CFIndex capacity; // Capacity in bytes
|
||||
unsigned int hasGap:1; // Currently unused
|
||||
unsigned int isFixedCapacity:1;
|
||||
unsigned int isExternalMutable:1;
|
||||
unsigned int capacityProvidedExternally:1;
|
||||
#if __LP64__
|
||||
unsigned long desiredCapacity:60;
|
||||
#else
|
||||
unsigned long desiredCapacity:28;
|
||||
#endif
|
||||
CFAllocatorRef contentsAllocator; // Optional
|
||||
}; // The only mutable variant for CFString
|
||||
|
||||
/* !!! Never do sizeof(CFString); the union is here just to make it easier to access some fields.
|
||||
*/
|
||||
struct __CFString {
|
||||
CFRuntimeBase base;
|
||||
union { // In many cases the allocated structs are smaller than these
|
||||
struct __inline1 {
|
||||
CFIndex length;
|
||||
} inline1; // Bytes follow the length
|
||||
struct __notInlineImmutable1 {
|
||||
void *buffer; // Note that the buffer is in the same place for all non-inline variants of CFString
|
||||
CFIndex length;
|
||||
CFAllocatorRef contentsDeallocator; // Optional; just the dealloc func is used
|
||||
} notInlineImmutable1; // This is the usual not-inline immutable CFString
|
||||
struct __notInlineImmutable2 {
|
||||
void *buffer;
|
||||
CFAllocatorRef contentsDeallocator; // Optional; just the dealloc func is used
|
||||
} notInlineImmutable2; // This is the not-inline immutable CFString when length is stored with the contents (first byte)
|
||||
struct __notInlineMutable notInlineMutable;
|
||||
} variants;
|
||||
};
|
||||
|
||||
/*
|
||||
I = is immutable
|
||||
E = not inline contents
|
||||
U = is Unicode
|
||||
N = has NULL byte
|
||||
L = has length byte
|
||||
D = explicit deallocator for contents (for mutable objects, allocator)
|
||||
C = length field is CFIndex (rather than UInt32); only meaningful for 64-bit, really
|
||||
if needed this bit (valuable real-estate) can be given up for another bit elsewhere, since this info is needed just for 64-bit
|
||||
|
||||
Also need (only for mutable)
|
||||
F = is fixed
|
||||
G = has gap
|
||||
Cap, DesCap = capacity
|
||||
|
||||
B7 B6 B5 B4 B3 B2 B1 B0
|
||||
U N L C I
|
||||
|
||||
B6 B5
|
||||
0 0 inline contents
|
||||
0 1 E (freed with default allocator)
|
||||
1 0 E (not freed)
|
||||
1 1 E D
|
||||
|
||||
!!! Note: Constant CFStrings use the bit patterns:
|
||||
C8 (11001000 = default allocator, not inline, not freed contents; 8-bit; has NULL byte; doesn't have length; is immutable)
|
||||
D0 (11010000 = default allocator, not inline, not freed contents; Unicode; is immutable)
|
||||
The bit usages should not be modified in a way that would effect these bit patterns.
|
||||
*/
|
||||
|
||||
enum {
|
||||
__kCFFreeContentsWhenDoneMask = 0x020,
|
||||
__kCFFreeContentsWhenDone = 0x020,
|
||||
__kCFContentsMask = 0x060,
|
||||
__kCFHasInlineContents = 0x000,
|
||||
__kCFNotInlineContentsNoFree = 0x040, // Don't free
|
||||
__kCFNotInlineContentsDefaultFree = 0x020, // Use allocator's free function
|
||||
__kCFNotInlineContentsCustomFree = 0x060, // Use a specially provided free function
|
||||
__kCFHasContentsAllocatorMask = 0x060,
|
||||
__kCFHasContentsAllocator = 0x060, // (For mutable strings) use a specially provided allocator
|
||||
__kCFHasContentsDeallocatorMask = 0x060,
|
||||
__kCFHasContentsDeallocator = 0x060,
|
||||
__kCFIsMutableMask = 0x01,
|
||||
__kCFIsMutable = 0x01,
|
||||
__kCFIsUnicodeMask = 0x10,
|
||||
__kCFIsUnicode = 0x10,
|
||||
__kCFHasNullByteMask = 0x08,
|
||||
__kCFHasNullByte = 0x08,
|
||||
__kCFHasLengthByteMask = 0x04,
|
||||
__kCFHasLengthByte = 0x04,
|
||||
// !!! Bit 0x02 has been freed up
|
||||
};
|
||||
|
||||
|
||||
// !!! Assumptions:
|
||||
// Mutable strings are not inline
|
||||
// Compile-time constant strings are not inline
|
||||
// Mutable strings always have explicit length (but they might also have length byte and null byte)
|
||||
// If there is an explicit length, always use that instead of the length byte (length byte is useful for quickly returning pascal strings)
|
||||
// Never look at the length byte for the length; use __CFStrLength or __CFStrLength2
|
||||
|
||||
/* The following set of functions and macros need to be updated on change to the bit configuration
|
||||
*/
|
||||
CF_INLINE Boolean __CFStrIsMutable(CFStringRef str) {return (str->base._cfinfo[CF_INFO_BITS] & __kCFIsMutableMask) == __kCFIsMutable;}
|
||||
CF_INLINE Boolean __CFStrIsInline(CFStringRef str) {return (str->base._cfinfo[CF_INFO_BITS] & __kCFContentsMask) == __kCFHasInlineContents;}
|
||||
CF_INLINE Boolean __CFStrFreeContentsWhenDone(CFStringRef str) {return (str->base._cfinfo[CF_INFO_BITS] & __kCFFreeContentsWhenDoneMask) == __kCFFreeContentsWhenDone;}
|
||||
CF_INLINE Boolean __CFStrHasContentsDeallocator(CFStringRef str) {return (str->base._cfinfo[CF_INFO_BITS] & __kCFHasContentsDeallocatorMask) == __kCFHasContentsDeallocator;}
|
||||
CF_INLINE Boolean __CFStrIsUnicode(CFStringRef str) {return (str->base._cfinfo[CF_INFO_BITS] & __kCFIsUnicodeMask) == __kCFIsUnicode;}
|
||||
CF_INLINE Boolean __CFStrIsEightBit(CFStringRef str) {return (str->base._cfinfo[CF_INFO_BITS] & __kCFIsUnicodeMask) != __kCFIsUnicode;}
|
||||
CF_INLINE Boolean __CFStrHasNullByte(CFStringRef str) {return (str->base._cfinfo[CF_INFO_BITS] & __kCFHasNullByteMask) == __kCFHasNullByte;}
|
||||
CF_INLINE Boolean __CFStrHasLengthByte(CFStringRef str) {return (str->base._cfinfo[CF_INFO_BITS] & __kCFHasLengthByteMask) == __kCFHasLengthByte;}
|
||||
CF_INLINE Boolean __CFStrHasExplicitLength(CFStringRef str) {return (str->base._cfinfo[CF_INFO_BITS] & (__kCFIsMutableMask | __kCFHasLengthByteMask)) != __kCFHasLengthByte;} // Has explicit length if (1) mutable or (2) not mutable and no length byte
|
||||
CF_INLINE Boolean __CFStrIsConstant(CFStringRef str) {
|
||||
#if __LP64__
|
||||
return str->base._rc == 0;
|
||||
#else
|
||||
return (str->base._cfinfo[CF_RC_BITS]) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Returns ptr to the buffer (which might include the length byte).
|
||||
*/
|
||||
CF_INLINE const void *__CFStrContents(CFStringRef str) {
|
||||
if (__CFStrIsInline(str)) {
|
||||
return (const void *)(((uintptr_t)&(str->variants)) + (__CFStrHasExplicitLength(str) ? sizeof(CFIndex) : 0));
|
||||
} else { // Not inline; pointer is always word 2
|
||||
return str->variants.notInlineImmutable1.buffer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - CF-1153.18/CFURL.c -
|
||||
// ======================================================================
|
||||
|
||||
struct __CFURL {
|
||||
CFRuntimeBase _cfBase;
|
||||
UInt32 _flags;
|
||||
CFStringEncoding _encoding; // The encoding to use when asked to remove percent escapes
|
||||
CFStringRef _string; // Never NULL
|
||||
CFURLRef _base;
|
||||
struct _CFURLAdditionalData* _extra;
|
||||
void *_resourceInfo; // For use by CoreServicesInternal to cache property values. Retained and released by CFURL.
|
||||
CFRange _ranges[1]; // variable length (1 to 9) array of ranges
|
||||
};
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - CF-1153.18/CFDate.c -
|
||||
// ======================================================================
|
||||
|
||||
struct __CFDate {
|
||||
// According to CFDate.c the structure is a CFRuntimeBase followed
|
||||
// by the time. In fact, it's only an isa pointer followed by the time.
|
||||
//struct CFRuntimeBase _base;
|
||||
uintptr_t _cfisa;
|
||||
CFAbsoluteTime _time; /* immutable */
|
||||
};
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - CF-1153.18/CFNumber.c -
|
||||
// ======================================================================
|
||||
|
||||
struct __CFNumber {
|
||||
CFRuntimeBase _base;
|
||||
uint64_t _pad; // need this space here for the constant objects
|
||||
/* 0 or 8 more bytes allocated here */
|
||||
};
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - CF-1153.18/CFArray.c -
|
||||
// ======================================================================
|
||||
|
||||
struct __CFArrayBucket {
|
||||
const void *_item;
|
||||
};
|
||||
|
||||
struct __CFArrayDeque {
|
||||
uintptr_t _leftIdx;
|
||||
uintptr_t _capacity;
|
||||
/* struct __CFArrayBucket buckets follow here */
|
||||
};
|
||||
|
||||
struct __CFArray {
|
||||
CFRuntimeBase _base;
|
||||
CFIndex _count; /* number of objects */
|
||||
CFIndex _mutations;
|
||||
int32_t _mutInProgress;
|
||||
/* __strong */ void *_store; /* can be NULL when MutableDeque */
|
||||
};
|
||||
|
||||
/* Flag bits */
|
||||
enum { /* Bits 0-1 */
|
||||
__kCFArrayImmutable = 0,
|
||||
__kCFArrayDeque = 2,
|
||||
};
|
||||
|
||||
enum { /* Bits 2-3 */
|
||||
__kCFArrayHasNullCallBacks = 0,
|
||||
__kCFArrayHasCFTypeCallBacks = 1,
|
||||
__kCFArrayHasCustomCallBacks = 3 /* callbacks are at end of header */
|
||||
};
|
||||
|
||||
CF_INLINE CFIndex __CFArrayGetType(CFArrayRef array) {
|
||||
return __CFBitfieldGetValue(((const CFRuntimeBase *)array)->_cfinfo[CF_INFO_BITS], 1, 0);
|
||||
}
|
||||
|
||||
CF_INLINE CFIndex __CFArrayGetSizeOfType(CFIndex t) {
|
||||
CFIndex size = 0;
|
||||
size += sizeof(struct __CFArray);
|
||||
if (__CFBitfieldGetValue((unsigned long)t, 3, 2) == __kCFArrayHasCustomCallBacks) {
|
||||
size += sizeof(CFArrayCallBacks);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Only applies to immutable and mutable-deque-using arrays;
|
||||
* Returns the bucket holding the left-most real value in the latter case. */
|
||||
CF_INLINE struct __CFArrayBucket *__CFArrayGetBucketsPtr(CFArrayRef array) {
|
||||
switch (__CFArrayGetType(array)) {
|
||||
case __kCFArrayImmutable:
|
||||
return (struct __CFArrayBucket *)((uint8_t *)array + __CFArrayGetSizeOfType(((CFRuntimeBase *)array)->_cfinfo[CF_INFO_BITS]));
|
||||
case __kCFArrayDeque: {
|
||||
struct __CFArrayDeque *deque = (struct __CFArrayDeque *)array->_store;
|
||||
return (struct __CFArrayBucket *)((uint8_t *)deque + sizeof(struct __CFArrayDeque) + deque->_leftIdx * sizeof(struct __CFArrayBucket));
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - CF-1153.18/CFBasicHash.h -
|
||||
// ======================================================================
|
||||
|
||||
typedef struct __CFBasicHash *CFBasicHashRef;
|
||||
typedef const struct __CFBasicHash *CFConstBasicHashRef;
|
||||
|
||||
typedef struct __CFBasicHashCallbacks CFBasicHashCallbacks;
|
||||
|
||||
struct __CFBasicHashCallbacks {
|
||||
uintptr_t (*retainValue)(CFAllocatorRef alloc, uintptr_t stack_value); // Return 2nd arg or new value
|
||||
uintptr_t (*retainKey)(CFAllocatorRef alloc, uintptr_t stack_key); // Return 2nd arg or new key
|
||||
void (*releaseValue)(CFAllocatorRef alloc, uintptr_t stack_value);
|
||||
void (*releaseKey)(CFAllocatorRef alloc, uintptr_t stack_key);
|
||||
Boolean (*equateValues)(uintptr_t coll_value1, uintptr_t stack_value2); // 1st arg is in-collection value, 2nd arg is probe parameter OR in-collection value for a second collection
|
||||
Boolean (*equateKeys)(uintptr_t coll_key1, uintptr_t stack_key2); // 1st arg is in-collection key, 2nd arg is probe parameter
|
||||
CFHashCode (*hashKey)(uintptr_t stack_key);
|
||||
uintptr_t (*getIndirectKey)(uintptr_t coll_value); // Return key; 1st arg is in-collection value
|
||||
CFStringRef (*copyValueDescription)(uintptr_t stack_value);
|
||||
CFStringRef (*copyKeyDescription)(uintptr_t stack_key);
|
||||
};
|
||||
|
||||
|
||||
// ======================================================================
|
||||
#pragma mark - CF-1153.18/CFBasicHash.c -
|
||||
// ======================================================================
|
||||
|
||||
// Prime numbers. Values above 100 have been adjusted up so that the
|
||||
// malloced block size will be just below a multiple of 512; values
|
||||
// above 1200 have been adjusted up to just below a multiple of 4096.
|
||||
static const uintptr_t __CFBasicHashTableSizes[64] = {
|
||||
0, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723,
|
||||
2803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607,
|
||||
214519, 346607, 561109, 907759, 1468927, 2376191, 3845119,
|
||||
6221311, 10066421, 16287743, 26354171, 42641881, 68996069,
|
||||
111638519, 180634607, 292272623, 472907251,
|
||||
#if __LP64__
|
||||
765180413UL, 1238087663UL, 2003267557UL, 3241355263UL, 5244622819UL,
|
||||
#if 0
|
||||
8485977589UL, 13730600407UL, 22216578047UL, 35947178479UL,
|
||||
58163756537UL, 94110934997UL, 152274691561UL, 246385626107UL,
|
||||
398660317687UL, 645045943807UL, 1043706260983UL, 1688752204787UL,
|
||||
2732458465769UL, 4421210670577UL, 7153669136377UL,
|
||||
11574879807461UL, 18728548943849UL, 30303428750843UL
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef union {
|
||||
uintptr_t neutral;
|
||||
void* Xstrong; // Changed from type 'id'
|
||||
void* Xweak; // Changed from type 'id'
|
||||
} CFBasicHashValue;
|
||||
|
||||
struct __CFBasicHash {
|
||||
CFRuntimeBase base;
|
||||
struct { // 192 bits
|
||||
uint16_t mutations;
|
||||
uint8_t hash_style:2;
|
||||
uint8_t keys_offset:1;
|
||||
uint8_t counts_offset:2;
|
||||
uint8_t counts_width:2;
|
||||
uint8_t hashes_offset:2;
|
||||
uint8_t strong_values:1;
|
||||
uint8_t strong_keys:1;
|
||||
uint8_t weak_values:1;
|
||||
uint8_t weak_keys:1;
|
||||
uint8_t int_values:1;
|
||||
uint8_t int_keys:1;
|
||||
uint8_t indirect_keys:1;
|
||||
uint32_t used_buckets; /* number of used buckets */
|
||||
uint64_t deleted:16;
|
||||
uint64_t num_buckets_idx:8; /* index to number of buckets */
|
||||
uint64_t __kret:10;
|
||||
uint64_t __vret:10;
|
||||
uint64_t __krel:10;
|
||||
uint64_t __vrel:10;
|
||||
uint64_t __:1;
|
||||
uint64_t null_rc:1;
|
||||
uint64_t fast_grow:1;
|
||||
uint64_t finalized:1;
|
||||
uint64_t __kdes:10;
|
||||
uint64_t __vdes:10;
|
||||
uint64_t __kequ:10;
|
||||
uint64_t __vequ:10;
|
||||
uint64_t __khas:10;
|
||||
uint64_t __kget:10;
|
||||
} bits;
|
||||
void *pointers[1];
|
||||
};
|
||||
|
||||
CF_INLINE CFBasicHashValue *__CFBasicHashGetValues(CFConstBasicHashRef ht) {
|
||||
return (CFBasicHashValue *)ht->pointers[0];
|
||||
}
|
||||
|
||||
CF_INLINE CFBasicHashValue *__CFBasicHashGetKeys(CFConstBasicHashRef ht) {
|
||||
return (CFBasicHashValue *)ht->pointers[ht->bits.keys_offset];
|
||||
}
|
||||
|
||||
CF_INLINE void *__CFBasicHashGetCounts(CFConstBasicHashRef ht) {
|
||||
return (void *)ht->pointers[ht->bits.counts_offset];
|
||||
}
|
||||
|
||||
CF_INLINE uintptr_t __CFBasicHashGetSlotCount(CFConstBasicHashRef ht, CFIndex idx) {
|
||||
void *counts = __CFBasicHashGetCounts(ht);
|
||||
switch (ht->bits.counts_width) {
|
||||
case 0: return ((uint8_t *)counts)[idx];
|
||||
case 1: return ((uint16_t *)counts)[idx];
|
||||
case 2: return ((uint32_t *)counts)[idx];
|
||||
case 3: return (uintptr_t)((uint64_t *)counts)[idx];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSObjCApple_h
|
||||
@@ -0,0 +1,228 @@
|
||||
//===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides Optional, a template class modeled in the spirit of
|
||||
// OCaml's 'opt' variant. The idea is to strongly type whether or not
|
||||
// a value can be optional.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_OPTIONAL_H
|
||||
#define LLVM_ADT_OPTIONAL_H
|
||||
|
||||
#include "None.h"
|
||||
#include "AlignOf.h"
|
||||
#include "Compiler.h"
|
||||
#include <cassert>
|
||||
#include <new>
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template<typename T>
|
||||
class Optional {
|
||||
AlignedCharArrayUnion<T> storage;
|
||||
bool hasVal;
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
Optional(NoneType) : hasVal(false) {}
|
||||
explicit Optional() : hasVal(false) {}
|
||||
Optional(const T &y) : hasVal(true) {
|
||||
new (storage.buffer) T(y);
|
||||
}
|
||||
Optional(const Optional &O) : hasVal(O.hasVal) {
|
||||
if (hasVal)
|
||||
new (storage.buffer) T(*O);
|
||||
}
|
||||
|
||||
Optional(T &&y) : hasVal(true) {
|
||||
new (storage.buffer) T(std::forward<T>(y));
|
||||
}
|
||||
Optional(Optional<T> &&O) : hasVal(O) {
|
||||
if (O) {
|
||||
new (storage.buffer) T(std::move(*O));
|
||||
O.reset();
|
||||
}
|
||||
}
|
||||
Optional &operator=(T &&y) {
|
||||
if (hasVal)
|
||||
**this = std::move(y);
|
||||
else {
|
||||
new (storage.buffer) T(std::move(y));
|
||||
hasVal = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Optional &operator=(Optional &&O) {
|
||||
if (!O)
|
||||
reset();
|
||||
else {
|
||||
*this = std::move(*O);
|
||||
O.reset();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Create a new object by constructing it in place with the given arguments.
|
||||
template<typename ...ArgTypes>
|
||||
void emplace(ArgTypes &&...Args) {
|
||||
reset();
|
||||
hasVal = true;
|
||||
new (storage.buffer) T(std::forward<ArgTypes>(Args)...);
|
||||
}
|
||||
|
||||
static inline Optional create(const T* y) {
|
||||
return y ? Optional(*y) : Optional();
|
||||
}
|
||||
|
||||
// FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
|
||||
// could be made more efficient by passing by value, possibly unifying them
|
||||
// with the rvalue versions above - but this could place a different set of
|
||||
// requirements (notably: the existence of a default ctor) when implemented
|
||||
// in that way. Careful SFINAE to avoid such pitfalls would be required.
|
||||
Optional &operator=(const T &y) {
|
||||
if (hasVal)
|
||||
**this = y;
|
||||
else {
|
||||
new (storage.buffer) T(y);
|
||||
hasVal = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Optional &operator=(const Optional &O) {
|
||||
if (!O)
|
||||
reset();
|
||||
else
|
||||
*this = *O;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
if (hasVal) {
|
||||
(**this).~T();
|
||||
hasVal = false;
|
||||
}
|
||||
}
|
||||
|
||||
~Optional() {
|
||||
reset();
|
||||
}
|
||||
|
||||
const T* getPointer() const { assert(hasVal); return reinterpret_cast<const T*>(storage.buffer); }
|
||||
T* getPointer() { assert(hasVal); return reinterpret_cast<T*>(storage.buffer); }
|
||||
const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
|
||||
T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
|
||||
|
||||
explicit operator bool() const { return hasVal; }
|
||||
bool hasValue() const { return hasVal; }
|
||||
const T* operator->() const { return getPointer(); }
|
||||
T* operator->() { return getPointer(); }
|
||||
const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
|
||||
T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
|
||||
|
||||
template <typename U>
|
||||
LLVM_CONSTEXPR T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION {
|
||||
return hasValue() ? getValue() : std::forward<U>(value);
|
||||
}
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCE_THIS
|
||||
T&& getValue() && { assert(hasVal); return std::move(*getPointer()); }
|
||||
T&& operator*() && { assert(hasVal); return std::move(*getPointer()); }
|
||||
|
||||
template <typename U>
|
||||
T getValueOr(U &&value) && {
|
||||
return hasValue() ? std::move(getValue()) : std::forward<U>(value);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename T> struct isPodLike;
|
||||
template <typename T> struct isPodLike<Optional<T> > {
|
||||
// An Optional<T> is pod-like if T is.
|
||||
static const bool value = isPodLike<T>::value;
|
||||
};
|
||||
|
||||
/// \brief Poison comparison between two \c Optional objects. Clients needs to
|
||||
/// explicitly compare the underlying values and account for empty \c Optional
|
||||
/// objects.
|
||||
///
|
||||
/// This routine will never be defined. It returns \c void to help diagnose
|
||||
/// errors at compile time.
|
||||
template<typename T, typename U>
|
||||
void operator==(const Optional<T> &X, const Optional<U> &Y);
|
||||
|
||||
template<typename T>
|
||||
bool operator==(const Optional<T> &X, NoneType) {
|
||||
return !X.hasValue();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator==(NoneType, const Optional<T> &X) {
|
||||
return X == None;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator!=(const Optional<T> &X, NoneType) {
|
||||
return !(X == None);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator!=(NoneType, const Optional<T> &X) {
|
||||
return X != None;
|
||||
}
|
||||
/// \brief Poison comparison between two \c Optional objects. Clients needs to
|
||||
/// explicitly compare the underlying values and account for empty \c Optional
|
||||
/// objects.
|
||||
///
|
||||
/// This routine will never be defined. It returns \c void to help diagnose
|
||||
/// errors at compile time.
|
||||
template<typename T, typename U>
|
||||
void operator!=(const Optional<T> &X, const Optional<U> &Y);
|
||||
|
||||
/// \brief Poison comparison between two \c Optional objects. Clients needs to
|
||||
/// explicitly compare the underlying values and account for empty \c Optional
|
||||
/// objects.
|
||||
///
|
||||
/// This routine will never be defined. It returns \c void to help diagnose
|
||||
/// errors at compile time.
|
||||
template<typename T, typename U>
|
||||
void operator<(const Optional<T> &X, const Optional<U> &Y);
|
||||
|
||||
/// \brief Poison comparison between two \c Optional objects. Clients needs to
|
||||
/// explicitly compare the underlying values and account for empty \c Optional
|
||||
/// objects.
|
||||
///
|
||||
/// This routine will never be defined. It returns \c void to help diagnose
|
||||
/// errors at compile time.
|
||||
template<typename T, typename U>
|
||||
void operator<=(const Optional<T> &X, const Optional<U> &Y);
|
||||
|
||||
/// \brief Poison comparison between two \c Optional objects. Clients needs to
|
||||
/// explicitly compare the underlying values and account for empty \c Optional
|
||||
/// objects.
|
||||
///
|
||||
/// This routine will never be defined. It returns \c void to help diagnose
|
||||
/// errors at compile time.
|
||||
template<typename T, typename U>
|
||||
void operator>=(const Optional<T> &X, const Optional<U> &Y);
|
||||
|
||||
/// \brief Poison comparison between two \c Optional objects. Clients needs to
|
||||
/// explicitly compare the underlying values and account for empty \c Optional
|
||||
/// objects.
|
||||
///
|
||||
/// This routine will never be defined. It returns \c void to help diagnose
|
||||
/// errors at compile time.
|
||||
template<typename T, typename U>
|
||||
void operator>(const Optional<T> &X, const Optional<U> &Y);
|
||||
|
||||
} // end llvm namespace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// KSReachability.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-05-05.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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/Foundation.h>
|
||||
#import "KSSystemCapabilities.h"
|
||||
#if KSCRASH_HAS_REACHABILITY
|
||||
#import <SystemConfiguration/SystemConfiguration.h>
|
||||
#endif
|
||||
|
||||
/** This is the notification name used in the Apple reachability example. */
|
||||
#define kDefaultNetworkReachabilityChangedNotification @"kNetworkReachabilityChangedNotification"
|
||||
|
||||
|
||||
/** Monitors network connectivity.
|
||||
*
|
||||
* Note: Upon construction, this object will fetch its initial reachability
|
||||
* state in the background. This means that the reachability status will ALWAYS
|
||||
* be "unreachable" until some time after object construction. If you want
|
||||
* the true reachability state before the current code block ends, you can call
|
||||
* updateFlags. Note, however, that it will probably block.
|
||||
*
|
||||
* You can elect to be notified via blocks (onReachabilityChanged),
|
||||
* notifications (notificationName), or KVO (flags, reachable, and WWANOnly).
|
||||
*
|
||||
* All notification methods are disabled by default.
|
||||
*/
|
||||
@interface KSReachabilityKSCrash : NSObject
|
||||
|
||||
#pragma mark Constructors
|
||||
|
||||
/** Reachability to a specific host.
|
||||
*
|
||||
* @param hostname The name or IP address of the host to monitor. If nil or
|
||||
* empty string, check reachability to the internet in general.
|
||||
*/
|
||||
+ (KSReachabilityKSCrash*) reachabilityToHost:(NSString*) hostname;
|
||||
|
||||
/** Reachability to the local (wired or wifi) network.
|
||||
*/
|
||||
+ (KSReachabilityKSCrash*) reachabilityToLocalNetwork;
|
||||
|
||||
|
||||
#pragma mark General Information
|
||||
|
||||
/** The host we are monitoring reachability to, if any. */
|
||||
@property(nonatomic,readonly,retain) NSString* hostname;
|
||||
|
||||
|
||||
#pragma mark Notifications and Callbacks
|
||||
|
||||
/** If non-nil, called whenever reachability flags change.
|
||||
* Block will be invoked on the main thread.
|
||||
*/
|
||||
@property(nonatomic,readwrite,copy) void(^onReachabilityChanged)(KSReachabilityKSCrash* reachability);
|
||||
|
||||
/** The notification to send when reachability changes (nil = don't send).
|
||||
* Default = nil
|
||||
*/
|
||||
@property(nonatomic,readwrite,retain) NSString* notificationName;
|
||||
|
||||
|
||||
#pragma mark KVO Compliant Status Properties
|
||||
|
||||
/** The current reachability flags. */
|
||||
#if KSCRASH_HAS_REACHABILITY
|
||||
@property(nonatomic,readonly,assign) SCNetworkReachabilityFlags flags;
|
||||
#endif
|
||||
|
||||
/** Whether the host is reachable or not. */
|
||||
@property(nonatomic,readonly,assign) BOOL reachable;
|
||||
|
||||
/* If YES, the host is only reachable by WWAN (iOS only). */
|
||||
@property(nonatomic,readonly,assign) BOOL WWANOnly;
|
||||
|
||||
|
||||
#pragma mark Utility
|
||||
|
||||
/** Force updating of the reachability flags.
|
||||
* This method will potentially block.
|
||||
*
|
||||
* @return YES if the flags were successfully updated.
|
||||
*/
|
||||
- (BOOL) updateFlags;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
/** A one-time operation to perform as soon as a host is deemed reachable.
|
||||
* The operation will only be performed once, regardless of how many times a
|
||||
* host becomes reachable.
|
||||
*/
|
||||
@interface KSReachableOperationKSCrash: NSObject
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* @param hostname The name or IP address of the host to monitor. If nil or
|
||||
* empty string, check reachability to the internet in general.
|
||||
* If hostname is a URL string, it will use the host portion.
|
||||
*
|
||||
* @param allowWWAN If NO, a WWAN-only connection is not enough to trigger
|
||||
* this operation.
|
||||
*
|
||||
* @param block The block to invoke when the host becomes reachable.
|
||||
* Block will be invoked on the main thread.
|
||||
*/
|
||||
+ (KSReachableOperationKSCrash*) operationWithHost:(NSString*) hostname
|
||||
allowWWAN:(BOOL) allowWWAN
|
||||
block:(void(^)(void)) block;
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* @param hostname The name or IP address of the host to monitor. If nil or
|
||||
* empty string, check reachability to the internet in general.
|
||||
* If hostname is a URL string, it will use the host portion.
|
||||
*
|
||||
* @param allowWWAN If NO, a WWAN-only connection is not enough to trigger
|
||||
* this operation.
|
||||
*
|
||||
* @param block The block to invoke when the host becomes reachable.
|
||||
* Block will be invoked on the main thread.
|
||||
*/
|
||||
- (id) initWithHost:(NSString*) hostname
|
||||
allowWWAN:(BOOL) allowWWAN
|
||||
block:(void(^)(void)) block;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// KSSignalInfo.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-03.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/* Information about the signals we are interested in for a crash reporter.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_KSSignalInfo_h
|
||||
#define HDR_KSSignalInfo_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/** Get the name of a signal.
|
||||
*
|
||||
* @param signal The signal.
|
||||
*
|
||||
* @return The signal's name or NULL if not found.
|
||||
*/
|
||||
const char* kssignal_signalName(int signal);
|
||||
|
||||
/** Get the name of a signal's subcode.
|
||||
*
|
||||
* @param signal The signal.
|
||||
*
|
||||
* @param code The signal's code.
|
||||
*
|
||||
* @return The code's name or NULL if not found.
|
||||
*/
|
||||
const char* kssignal_signalCodeName(int signal, int code);
|
||||
|
||||
/** Get a list of fatal signals.
|
||||
*
|
||||
* @return A list of fatal signals.
|
||||
*/
|
||||
const int* kssignal_fatalSignals(void);
|
||||
|
||||
/** Get the size of the fatal signals list.
|
||||
*
|
||||
* @return The size of the fatal signals list.
|
||||
*/
|
||||
int kssignal_numFatalSignals(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSSignalInfo_h
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// KSString.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-09-15.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef HDR_KSString_h
|
||||
#define HDR_KSString_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/** Check if a memory location contains a null terminated UTF-8 string.
|
||||
*
|
||||
* @param memory The memory location to test.
|
||||
*
|
||||
* @param minLength The minimum length to be considered a valid string.
|
||||
*
|
||||
* @param maxLength The maximum length to be considered a valid string.
|
||||
*/
|
||||
bool ksstring_isNullTerminatedUTF8String(const void* memory, int minLength, int maxLength);
|
||||
|
||||
/** Extract a hex value in the form "0x123456789abcdef" from a string.
|
||||
*
|
||||
* @param string The string to search.
|
||||
*
|
||||
* @param stringLength The length of the string.
|
||||
*
|
||||
* @param result Buffer to hold the resulting value.
|
||||
*
|
||||
* @return true if the operation was successful.
|
||||
*/
|
||||
bool ksstring_extractHexValue(const char* string, int stringLength, uint64_t* result);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSString_h
|
||||
@@ -0,0 +1,191 @@
|
||||
//
|
||||
// KSSysCtl.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-19.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/* Convenience wrapper functions for sysctl calls.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_KSSysCtl_h
|
||||
#define HDR_KSSysCtl_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
|
||||
/** Get an int32 value via sysctl.
|
||||
*
|
||||
* @param major_cmd The major part of the command or name.
|
||||
*
|
||||
* @param minor_cmd The minor part of the command or name.
|
||||
*
|
||||
* @return The value returned by sysctl.
|
||||
*/
|
||||
int32_t kssysctl_int32(int major_cmd, int minor_cmd);
|
||||
|
||||
/** Get an int32 value via sysctl by name.
|
||||
*
|
||||
* @param name The name of the command.
|
||||
*
|
||||
* @return The value returned by sysctl.
|
||||
*/
|
||||
int32_t kssysctl_int32ForName(const char* name);
|
||||
|
||||
/** Get a uint32 value via sysctl.
|
||||
*
|
||||
* @param major_cmd The major part of the command or name.
|
||||
*
|
||||
* @param minor_cmd The minor part of the command or name.
|
||||
*
|
||||
* @return The value returned by sysctl.
|
||||
*/
|
||||
uint32_t kssysctl_uint32(int major_cmd, int minor_cmd);
|
||||
|
||||
/** Get a uint32 value via sysctl by name.
|
||||
*
|
||||
* @param name The name of the command.
|
||||
*
|
||||
* @return The value returned by sysctl.
|
||||
*/
|
||||
uint32_t kssysctl_uint32ForName(const char* name);
|
||||
|
||||
/** Get an int64 value via sysctl.
|
||||
*
|
||||
* @param major_cmd The major part of the command or name.
|
||||
*
|
||||
* @param minor_cmd The minor part of the command or name.
|
||||
*
|
||||
* @return The value returned by sysctl.
|
||||
*/
|
||||
int64_t kssysctl_int64(int major_cmd, int minor_cmd);
|
||||
|
||||
/** Get an int64 value via sysctl by name.
|
||||
*
|
||||
* @param name The name of the command.
|
||||
*
|
||||
* @return The value returned by sysctl.
|
||||
*/
|
||||
int64_t kssysctl_int64ForName(const char* name);
|
||||
|
||||
/** Get a uint64 value via sysctl.
|
||||
*
|
||||
* @param major_cmd The major part of the command or name.
|
||||
*
|
||||
* @param minor_cmd The minor part of the command or name.
|
||||
*
|
||||
* @return The value returned by sysctl.
|
||||
*/
|
||||
uint64_t kssysctl_uint64(int major_cmd, int minor_cmd);
|
||||
|
||||
/** Get a uint64 value via sysctl by name.
|
||||
*
|
||||
* @param name The name of the command.
|
||||
*
|
||||
* @return The value returned by sysctl.
|
||||
*/
|
||||
uint64_t kssysctl_uint64ForName(const char* name);
|
||||
|
||||
/** Get a string value via sysctl.
|
||||
*
|
||||
* @param major_cmd The major part of the command or name.
|
||||
*
|
||||
* @param minor_cmd The minor part of the command or name.
|
||||
*
|
||||
* @param value Pointer to a buffer to fill out. If NULL, does not fill
|
||||
* anything out.
|
||||
*
|
||||
* @param maxSize The size of the buffer pointed to by value.
|
||||
*
|
||||
* @return The number of bytes written (or that would have been written if
|
||||
* value is NULL).
|
||||
*/
|
||||
int kssysctl_string(int major_cmd, int minor_cmd, char* value, int maxSize);
|
||||
|
||||
/** Get a string value via sysctl by name.
|
||||
*
|
||||
* @param name The name of the command.
|
||||
*
|
||||
* @param value Pointer to a buffer to fill out. If NULL, does not fill
|
||||
* anything out.
|
||||
*
|
||||
* @param maxSize The size of the buffer pointed to by value.
|
||||
*
|
||||
* @return The number of bytes written (or that would have been written if
|
||||
* value is NULL).
|
||||
*/
|
||||
int kssysctl_stringForName(const char* name, char* value, int maxSize);
|
||||
|
||||
/** Get a timeval value via sysctl.
|
||||
*
|
||||
* @param major_cmd The major part of the command or name.
|
||||
*
|
||||
* @param minor_cmd The minor part of the command or name.
|
||||
*
|
||||
* @return The value returned by sysctl.
|
||||
*/
|
||||
struct timeval kssysctl_timeval(int major_cmd, int minor_cmd);
|
||||
|
||||
/** Get a timeval value via sysctl by name.
|
||||
*
|
||||
* @param name The name of the command.
|
||||
*
|
||||
* @return The value returned by sysctl.
|
||||
*/
|
||||
struct timeval kssysctl_timevalForName(const char* name);
|
||||
|
||||
/** Get information about a process.
|
||||
*
|
||||
* @param pid The process ID.
|
||||
*
|
||||
* @param procInfo Struct to hold the proces information.
|
||||
*
|
||||
* @return true if the operation was successful.
|
||||
*/
|
||||
bool kssysctl_getProcessInfo(int pid, struct kinfo_proc* procInfo);
|
||||
|
||||
/** Get the MAC address of the specified interface.
|
||||
* Note: As of iOS 7 this will always return a fixed value of 02:00:00:00:00:00.
|
||||
*
|
||||
* @param name Interface name (e.g. "en1").
|
||||
*
|
||||
* @param macAddressBuffer 6 bytes of storage to hold the MAC address.
|
||||
*
|
||||
* @return true if the address was successfully retrieved.
|
||||
*/
|
||||
bool kssysctl_getMacAddress(const char* name, char* macAddressBuffer);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSSysCtl_h
|
||||
@@ -0,0 +1,154 @@
|
||||
//
|
||||
// KSSystemCapabilities.h
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
#ifndef HDR_KSSystemCapabilities_h
|
||||
#define HDR_KSSystemCapabilities_h
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
#define KSCRASH_HOST_APPLE 1
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#define KSCRASH_HOST_ANDROID 1
|
||||
#endif
|
||||
|
||||
#define KSCRASH_HOST_IOS (KSCRASH_HOST_APPLE && TARGET_OS_IOS)
|
||||
#define KSCRASH_HOST_TV (KSCRASH_HOST_APPLE && TARGET_OS_TV)
|
||||
#define KSCRASH_HOST_WATCH (KSCRASH_HOST_APPLE && TARGET_OS_WATCH)
|
||||
#define KSCRASH_HOST_MAC (KSCRASH_HOST_APPLE && TARGET_OS_MAC && !(TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH))
|
||||
|
||||
#if KSCRASH_HOST_APPLE
|
||||
#define KSCRASH_CAN_GET_MAC_ADDRESS 1
|
||||
#else
|
||||
#define KSCRASH_CAN_GET_MAC_ADDRESS 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_APPLE
|
||||
#define KSCRASH_HAS_OBJC 1
|
||||
#define KSCRASH_HAS_SWIFT 1
|
||||
#else
|
||||
#define KSCRASH_HAS_OBJC 0
|
||||
#define KSCRASH_HAS_SWIFT 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_APPLE
|
||||
#define KSCRASH_HAS_KINFO_PROC 1
|
||||
#else
|
||||
#define KSCRASH_HAS_KINFO_PROC 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_APPLE
|
||||
#define KSCRASH_HAS_STRNSTR 1
|
||||
#else
|
||||
#define KSCRASH_HAS_STRNSTR 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_IOS || KSCRASH_HOST_TV || KSCRASH_HOST_WATCH
|
||||
#define KSCRASH_HAS_UIKIT 1
|
||||
#else
|
||||
#define KSCRASH_HAS_UIKIT 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_IOS || KSCRASH_HOST_TV
|
||||
#define KSCRASH_HAS_UIAPPLICATION 1
|
||||
#else
|
||||
#define KSCRASH_HAS_UIAPPLICATION 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_WATCH
|
||||
#define KSCRASH_HAS_NSEXTENSION 1
|
||||
#else
|
||||
#define KSCRASH_HAS_NSEXTENSION 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_IOS
|
||||
#define KSCRASH_HAS_MESSAGEUI 1
|
||||
#else
|
||||
#define KSCRASH_HAS_MESSAGEUI 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_IOS || KSCRASH_HOST_TV
|
||||
#define KSCRASH_HAS_UIDEVICE 1
|
||||
#else
|
||||
#define KSCRASH_HAS_UIDEVICE 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_IOS || KSCRASH_HOST_MAC || KSCRASH_HOST_TV
|
||||
#define KSCRASH_HAS_ALERTVIEW 1
|
||||
#else
|
||||
#define KSCRASH_HAS_ALERTVIEW 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_IOS
|
||||
#define KSCRASH_HAS_UIALERTVIEW 1
|
||||
#else
|
||||
#define KSCRASH_HAS_UIALERTVIEW 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_TV
|
||||
#define KSCRASH_HAS_UIALERTCONTROLLER 1
|
||||
#else
|
||||
#define KSCRASH_HAS_UIALERTCONTROLLER 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_MAC
|
||||
#define KSCRASH_HAS_NSALERT 1
|
||||
#else
|
||||
#define KSCRASH_HAS_NSALERT 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_IOS || KSCRASH_HOST_MAC
|
||||
#define KSCRASH_HAS_MACH 1
|
||||
#else
|
||||
#define KSCRASH_HAS_MACH 0
|
||||
#endif
|
||||
|
||||
// WatchOS signal is broken as of 3.1
|
||||
#if KSCRASH_HOST_ANDROID || KSCRASH_HOST_IOS || KSCRASH_HOST_MAC || KSCRASH_HOST_TV
|
||||
#define KSCRASH_HAS_SIGNAL 1
|
||||
#else
|
||||
#define KSCRASH_HAS_SIGNAL 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_ANDROID || KSCRASH_HOST_MAC || KSCRASH_HOST_IOS
|
||||
#define KSCRASH_HAS_SIGNAL_STACK 1
|
||||
#else
|
||||
#define KSCRASH_HAS_SIGNAL_STACK 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_MAC || KSCRASH_HOST_IOS || KSCRASH_HOST_TV
|
||||
#define KSCRASH_HAS_THREADS_API 1
|
||||
#else
|
||||
#define KSCRASH_HAS_THREADS_API 0
|
||||
#endif
|
||||
|
||||
#if KSCRASH_HOST_MAC || KSCRASH_HOST_IOS || KSCRASH_HOST_TV
|
||||
#define KSCRASH_HAS_REACHABILITY 1
|
||||
#else
|
||||
#define KSCRASH_HAS_REACHABILITY 0
|
||||
#endif
|
||||
|
||||
#endif // HDR_KSSystemCapabilities_h
|
||||
@@ -0,0 +1,103 @@
|
||||
//
|
||||
// KSVarArgs.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-08-19.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
/* KSVarArgs is a set of macros designed to make dealing with variable arguments
|
||||
* easier in Objective-C. All macros assume that the varargs list contains only
|
||||
* objective-c objects or object-like structures (assignable to type id).
|
||||
*
|
||||
* The base macro ksva_iterate_list() iterates over the variable arguments,
|
||||
* invoking a block for each argument, until it encounters a terminating nil.
|
||||
*
|
||||
* The other macros are for convenience when converting to common collections.
|
||||
*/
|
||||
|
||||
|
||||
/** Block type used by ksva_iterate_list.
|
||||
*
|
||||
* @param entry The current argument in the vararg list.
|
||||
*/
|
||||
typedef void (^KSVA_Block)(id entry);
|
||||
|
||||
|
||||
/**
|
||||
* Iterate over a va_list, executing the specified code block for each entry.
|
||||
*
|
||||
* @param FIRST_ARG_NAME The name of the first argument in the vararg list.
|
||||
* @param BLOCK A code block of type KSVA_Block.
|
||||
*/
|
||||
#define ksva_iterate_list(FIRST_ARG_NAME, BLOCK) \
|
||||
{ \
|
||||
KSVA_Block ksva_block = BLOCK; \
|
||||
va_list ksva_args; \
|
||||
va_start(ksva_args,FIRST_ARG_NAME); \
|
||||
for(id ksva_arg = FIRST_ARG_NAME; ksva_arg != nil; ksva_arg = va_arg(ksva_args, id)) \
|
||||
{ \
|
||||
ksva_block(ksva_arg); \
|
||||
} \
|
||||
va_end(ksva_args); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a variable argument list into an array. An autoreleased
|
||||
* NSMutableArray will be created in the current scope with the specified name.
|
||||
*
|
||||
* @param FIRST_ARG_NAME The name of the first argument in the vararg list.
|
||||
* @param ARRAY_NAME The name of the array to create in the current scope.
|
||||
*/
|
||||
#define ksva_list_to_nsarray(FIRST_ARG_NAME, ARRAY_NAME) \
|
||||
NSMutableArray* ARRAY_NAME = [NSMutableArray array]; \
|
||||
ksva_iterate_list(FIRST_ARG_NAME, ^(id entry) \
|
||||
{ \
|
||||
[ARRAY_NAME addObject:entry]; \
|
||||
})
|
||||
|
||||
/**
|
||||
* Convert a variable argument list into a dictionary, interpreting the vararg
|
||||
* list as object, key, object, key, ...
|
||||
* An autoreleased NSMutableDictionary will be created in the current scope with
|
||||
* the specified name.
|
||||
*
|
||||
* @param FIRST_ARG_NAME The name of the first argument in the vararg list.
|
||||
* @param DICT_NAME The name of the dictionary to create in the current scope.
|
||||
*/
|
||||
#define ksva_list_to_nsdictionary(FIRST_ARG_NAME, DICT_NAME) \
|
||||
NSMutableDictionary* DICT_NAME = [NSMutableDictionary dictionary]; \
|
||||
{ \
|
||||
__block id ksva_object = nil; \
|
||||
ksva_iterate_list(FIRST_ARG_NAME, ^(id entry) \
|
||||
{ \
|
||||
if(ksva_object == nil) \
|
||||
{ \
|
||||
ksva_object = entry; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
[DICT_NAME setObject:ksva_object forKey:entry]; \
|
||||
ksva_object = nil; \
|
||||
} \
|
||||
}); \
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
//===--- LLVM.h - Import various common LLVM datatypes ----------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file forward declares and imports various common LLVM datatypes that
|
||||
// swift wants to use unqualified.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_BASIC_LLVM_H
|
||||
#define SWIFT_BASIC_LLVM_H
|
||||
|
||||
// Do not proliferate #includes here, require clients to #include their
|
||||
// dependencies.
|
||||
// Casting.h has complex templates that cannot be easily forward declared.
|
||||
#include "Casting.h"
|
||||
// None.h includes an enumerator that is desired & cannot be forward declared
|
||||
// without a definition of NoneType.
|
||||
#include "None.h"
|
||||
|
||||
// Forward declarations.
|
||||
namespace llvm {
|
||||
// Containers.
|
||||
class StringRef;
|
||||
class StringLiteral;
|
||||
class Twine;
|
||||
template <typename T> class SmallPtrSetImpl;
|
||||
template <typename T, unsigned N> class SmallPtrSet;
|
||||
template <typename T> class SmallVectorImpl;
|
||||
template <typename T, unsigned N> class SmallVector;
|
||||
template <unsigned N> class SmallString;
|
||||
template <typename T, unsigned N> class SmallSetVector;
|
||||
template<typename T> class ArrayRef;
|
||||
template<typename T> class MutableArrayRef;
|
||||
template<typename T> class TinyPtrVector;
|
||||
template<typename T> class Optional;
|
||||
template <typename PT1, typename PT2> class PointerUnion;
|
||||
class SmallBitVector;
|
||||
|
||||
// Other common classes.
|
||||
class raw_ostream;
|
||||
class APInt;
|
||||
class APFloat;
|
||||
template <typename Fn> class function_ref;
|
||||
} // end namespace llvm
|
||||
|
||||
|
||||
namespace swift {
|
||||
// Casting operators.
|
||||
using llvm::isa;
|
||||
using llvm::cast;
|
||||
using llvm::dyn_cast;
|
||||
using llvm::dyn_cast_or_null;
|
||||
using llvm::cast_or_null;
|
||||
|
||||
// Containers.
|
||||
using llvm::None;
|
||||
using llvm::Optional;
|
||||
using llvm::SmallPtrSetImpl;
|
||||
using llvm::SmallPtrSet;
|
||||
using llvm::SmallString;
|
||||
using llvm::StringRef;
|
||||
using llvm::StringLiteral;
|
||||
using llvm::Twine;
|
||||
using llvm::SmallVectorImpl;
|
||||
using llvm::SmallVector;
|
||||
using llvm::ArrayRef;
|
||||
using llvm::MutableArrayRef;
|
||||
using llvm::TinyPtrVector;
|
||||
using llvm::PointerUnion;
|
||||
using llvm::SmallSetVector;
|
||||
using llvm::SmallBitVector;
|
||||
|
||||
// Other common classes.
|
||||
using llvm::APFloat;
|
||||
using llvm::APInt;
|
||||
using llvm::function_ref;
|
||||
using llvm::NoneType;
|
||||
using llvm::raw_ostream;
|
||||
} // end namespace swift
|
||||
|
||||
#endif // SWIFT_BASIC_LLVM_H
|
||||
@@ -0,0 +1,59 @@
|
||||
//===--- Malloc.h - Aligned malloc interface --------------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides an implementation of C11 aligned_alloc(3) for platforms
|
||||
// that don't have it yet, using posix_memalign(3).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_BASIC_MALLOC_H
|
||||
#define SWIFT_BASIC_MALLOC_H
|
||||
|
||||
#include <cassert>
|
||||
#if defined(_MSC_VER)
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
namespace swift {
|
||||
|
||||
// FIXME: Use C11 aligned_alloc if available.
|
||||
inline void *AlignedAlloc(size_t size, size_t align) {
|
||||
// posix_memalign only accepts alignments greater than sizeof(void*).
|
||||
//
|
||||
if (align < sizeof(void*))
|
||||
align = sizeof(void*);
|
||||
|
||||
void *r;
|
||||
#if defined(_WIN32)
|
||||
r = _aligned_malloc(size, align);
|
||||
assert(r && "_aligned_malloc failed");
|
||||
#else
|
||||
int res = posix_memalign(&r, align, size);
|
||||
assert(res == 0 && "posix_memalign failed");
|
||||
(void)res; // Silence the unused variable warning.
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
inline void AlignedFree(void *p) {
|
||||
#if defined(_WIN32)
|
||||
_aligned_free(p);
|
||||
#else
|
||||
free(p);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif // SWIFT_BASIC_MALLOC_H
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// NSError+SimpleConstructor.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2013-02-09.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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/Foundation.h>
|
||||
|
||||
/**
|
||||
* Simpler interface for constructing NSError objects.
|
||||
*/
|
||||
@interface NSError (SimpleConstructor)
|
||||
|
||||
/** Convenience constructor to make an error with the specified localized description.
|
||||
*
|
||||
* @param domain The domain
|
||||
* @param code The code
|
||||
* @param fmt Description of the error (gets placed into the user data with the key
|
||||
* NSLocalizedDescriptionKey).
|
||||
*/
|
||||
+ (NSError*) errorWithDomain:(NSString*) domain
|
||||
code:(NSInteger) code
|
||||
description:(NSString*) fmt, ...;
|
||||
|
||||
/** Fill an error pointer with an NSError object if it's not nil.
|
||||
*
|
||||
* @param error Error pointer to fill (ignored if nil).
|
||||
* @param domain The domain
|
||||
* @param code The code
|
||||
* @param fmt Description of the error (gets placed into the user data with the key
|
||||
* NSLocalizedDescriptionKey).
|
||||
* @return NO (to keep the analyzer happy).
|
||||
*/
|
||||
+ (BOOL) fillError:(NSError**) error
|
||||
withDomain:(NSString*) domain
|
||||
code:(NSInteger) code
|
||||
description:(NSString*) fmt, ...;
|
||||
|
||||
/** Clear a pointer-to-error to nil of its pointer is not nil.
|
||||
*
|
||||
* @param error Error pointer to fill (ignored if nil).
|
||||
* @return NO (to keep the analyzer happy).
|
||||
*/
|
||||
+ (BOOL) clearError:(NSError**) error;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// NSMutableData+AppendUTF8.h
|
||||
//
|
||||
// Created by Karl Stenerud on 2012-02-26.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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/Foundation.h>
|
||||
|
||||
|
||||
/** Encodes strings to UTF-8 format.
|
||||
*/
|
||||
@interface NSMutableData (AppendUTF8)
|
||||
|
||||
/** Append a string encoded as UTF-8.
|
||||
*
|
||||
* @param format Printf-stype format.
|
||||
*/
|
||||
- (void) appendUTF8Format:(NSString*) format, ...;
|
||||
|
||||
/** Append a string encoded as UTF-8.
|
||||
*
|
||||
* @param string The string to append.
|
||||
*/
|
||||
- (void) appendUTF8String:(NSString*) string;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// NSString+URLEncode.h
|
||||
//
|
||||
// Created by karl on 2016-04-11.
|
||||
//
|
||||
// Copyright (c) 2012 Karl Stenerud. 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 remain in place
|
||||
// in this source code.
|
||||
//
|
||||
// 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/Foundation.h>
|
||||
|
||||
@interface NSString (URLEncode)
|
||||
|
||||
- (NSString*) URLEncoded;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,26 @@
|
||||
//===-- None.h - Simple null value for implicit construction ------*- C++ -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides None, an enumerator for use in implicit constructors
|
||||
// of various (usually templated) types to make such construction more
|
||||
// terse.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_NONE_H
|
||||
#define LLVM_ADT_NONE_H
|
||||
|
||||
namespace llvm {
|
||||
/// \brief A simple null object to allow implicit construction of Optional<T>
|
||||
/// and similar types without having to spell out the specialization's name.
|
||||
enum class NoneType { None };
|
||||
const NoneType None = None;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
//===--- Punycode.h - UTF-8 to Punycode transcoding -------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// These functions implement a variant of the Punycode algorithm from RFC3492,
|
||||
// originally designed for encoding international domain names, for the purpose
|
||||
// of encoding Swift identifiers into mangled symbol names. This version differs
|
||||
// from RFC3492 in the following respects:
|
||||
// - '_' is used as the encoding delimiter instead of '-'.
|
||||
// - Encoding digits are represented using [a-zA-J] instead of [a-z0-9], because
|
||||
// symbol names are case-sensitive, and Swift mangled identifiers cannot begin
|
||||
// with a digit.
|
||||
// - Optionally, non-symbol ASCII characters (characters except [$_a-zA-Z0-9])
|
||||
// are mapped to the code range 0xD800 - 0xD880 and are also encoded like
|
||||
// non-ASCII unicode characters.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_DEMANGLING_PUNYCODE_H
|
||||
#define SWIFT_DEMANGLING_PUNYCODE_H
|
||||
|
||||
#include "StringRef.h"
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace swift {
|
||||
namespace Punycode {
|
||||
|
||||
using llvm::StringRef;
|
||||
|
||||
/// Encodes a sequence of code points into Punycode.
|
||||
///
|
||||
/// Returns false if input contains surrogate code points.
|
||||
bool encodePunycode(const std::vector<uint32_t> &InputCodePoints,
|
||||
std::string &OutPunycode);
|
||||
|
||||
/// Decodes a Punycode string into a sequence of Unicode scalars.
|
||||
///
|
||||
/// Returns false if decoding failed.
|
||||
bool decodePunycode(StringRef InputPunycode,
|
||||
std::vector<uint32_t> &OutCodePoints);
|
||||
|
||||
/// Encodes an UTF8 string into Punycode.
|
||||
///
|
||||
/// If \p mapNonSymbolChars is true, non-symbol ASCII characters (characters
|
||||
/// except [$_a-zA-Z0-9]) are also encoded like non-ASCII unicode characters.
|
||||
/// Returns false if \p InputUTF8 contains surrogate code points.
|
||||
bool encodePunycodeUTF8(StringRef InputUTF8, std::string &OutPunycode,
|
||||
bool mapNonSymbolChars = false);
|
||||
|
||||
bool decodePunycodeUTF8(StringRef InputPunycode, std::string &OutUTF8);
|
||||
|
||||
} // end namespace Punycode
|
||||
} // end namespace swift
|
||||
|
||||
#endif // SWIFT_DEMANGLING_PUNYCODE_H
|
||||
@@ -0,0 +1,606 @@
|
||||
//===--- StringRef.h - Constant String Reference Wrapper --------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_STRINGREF_H
|
||||
#define LLVM_ADT_STRINGREF_H
|
||||
|
||||
#include "Compiler.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
template <typename T>
|
||||
class SmallVectorImpl;
|
||||
class APInt;
|
||||
class hash_code;
|
||||
class StringRef;
|
||||
|
||||
/// Helper functions for StringRef::getAsInteger.
|
||||
bool getAsUnsignedInteger(StringRef Str, unsigned Radix,
|
||||
unsigned long long &Result);
|
||||
|
||||
bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result);
|
||||
|
||||
/// StringRef - Represent a constant reference to a string, i.e. a character
|
||||
/// array and a length, which need not be null terminated.
|
||||
///
|
||||
/// This class does not own the string data, it is expected to be used in
|
||||
/// situations where the character data resides in some other buffer, whose
|
||||
/// lifetime extends past that of the StringRef. For this reason, it is not in
|
||||
/// general safe to store a StringRef.
|
||||
class StringRef {
|
||||
public:
|
||||
typedef const char *iterator;
|
||||
typedef const char *const_iterator;
|
||||
static const size_t npos = ~size_t(0);
|
||||
typedef size_t size_type;
|
||||
|
||||
private:
|
||||
/// The start of the string, in an external buffer.
|
||||
const char *Data;
|
||||
|
||||
/// The length of the string.
|
||||
size_t Length;
|
||||
|
||||
// Workaround memcmp issue with null pointers (undefined behavior)
|
||||
// by providing a specialized version
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) {
|
||||
if (Length == 0) { return 0; }
|
||||
return ::memcmp(Lhs,Rhs,Length);
|
||||
}
|
||||
|
||||
public:
|
||||
/// @name Constructors
|
||||
/// @{
|
||||
|
||||
/// Construct an empty string ref.
|
||||
/*implicit*/ StringRef() : Data(nullptr), Length(0) {}
|
||||
|
||||
/// Construct a string ref from a cstring.
|
||||
/*implicit*/ StringRef(const char *Str)
|
||||
: Data(Str) {
|
||||
assert(Str && "StringRef cannot be built from a NULL argument");
|
||||
Length = ::strlen(Str); // invoking strlen(NULL) is undefined behavior
|
||||
}
|
||||
|
||||
/// Construct a string ref from a pointer and length.
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
/*implicit*/ StringRef(const char *data, size_t length)
|
||||
: Data(data), Length(length) {
|
||||
assert((data || length == 0) &&
|
||||
"StringRef cannot be built from a NULL argument with non-null length");
|
||||
}
|
||||
|
||||
/// Construct a string ref from an std::string.
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
/*implicit*/ StringRef(const std::string &Str)
|
||||
: Data(Str.data()), Length(Str.length()) {}
|
||||
|
||||
/// @}
|
||||
/// @name Iterators
|
||||
/// @{
|
||||
|
||||
iterator begin() const { return Data; }
|
||||
|
||||
iterator end() const { return Data + Length; }
|
||||
|
||||
const unsigned char *bytes_begin() const {
|
||||
return reinterpret_cast<const unsigned char *>(begin());
|
||||
}
|
||||
const unsigned char *bytes_end() const {
|
||||
return reinterpret_cast<const unsigned char *>(end());
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name String Operations
|
||||
/// @{
|
||||
|
||||
/// data - Get a pointer to the start of the string (which may not be null
|
||||
/// terminated).
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
const char *data() const { return Data; }
|
||||
|
||||
/// empty - Check if the string is empty.
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
bool empty() const { return Length == 0; }
|
||||
|
||||
/// size - Get the string size.
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
size_t size() const { return Length; }
|
||||
|
||||
/// front - Get the first character in the string.
|
||||
char front() const {
|
||||
assert(!empty());
|
||||
return Data[0];
|
||||
}
|
||||
|
||||
/// back - Get the last character in the string.
|
||||
char back() const {
|
||||
assert(!empty());
|
||||
return Data[Length-1];
|
||||
}
|
||||
|
||||
// copy - Allocate copy in Allocator and return StringRef to it.
|
||||
template <typename Allocator> StringRef copy(Allocator &A) const {
|
||||
char *S = A.template Allocate<char>(Length);
|
||||
std::copy(begin(), end(), S);
|
||||
return StringRef(S, Length);
|
||||
}
|
||||
|
||||
/// equals - Check for string equality, this is more efficient than
|
||||
/// compare() when the relative ordering of inequal strings isn't needed.
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
bool equals(StringRef RHS) const {
|
||||
return (Length == RHS.Length &&
|
||||
compareMemory(Data, RHS.Data, RHS.Length) == 0);
|
||||
}
|
||||
|
||||
/// equals_lower - Check for string equality, ignoring case.
|
||||
bool equals_lower(StringRef RHS) const {
|
||||
return Length == RHS.Length && compare_lower(RHS) == 0;
|
||||
}
|
||||
|
||||
/// compare - Compare two strings; the result is -1, 0, or 1 if this string
|
||||
/// is lexicographically less than, equal to, or greater than the \p RHS.
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
int compare(StringRef RHS) const {
|
||||
// Check the prefix for a mismatch.
|
||||
if (int Res = compareMemory(Data, RHS.Data, std::min(Length, RHS.Length)))
|
||||
return Res < 0 ? -1 : 1;
|
||||
|
||||
// Otherwise the prefixes match, so we only need to check the lengths.
|
||||
if (Length == RHS.Length)
|
||||
return 0;
|
||||
return Length < RHS.Length ? -1 : 1;
|
||||
}
|
||||
|
||||
/// compare_lower - Compare two strings, ignoring case.
|
||||
int compare_lower(StringRef RHS) const;
|
||||
|
||||
/// compare_numeric - Compare two strings, treating sequences of digits as
|
||||
/// numbers.
|
||||
int compare_numeric(StringRef RHS) const;
|
||||
|
||||
/// \brief Determine the edit distance between this string and another
|
||||
/// string.
|
||||
///
|
||||
/// \param Other the string to compare this string against.
|
||||
///
|
||||
/// \param AllowReplacements whether to allow character
|
||||
/// replacements (change one character into another) as a single
|
||||
/// operation, rather than as two operations (an insertion and a
|
||||
/// removal).
|
||||
///
|
||||
/// \param MaxEditDistance If non-zero, the maximum edit distance that
|
||||
/// this routine is allowed to compute. If the edit distance will exceed
|
||||
/// that maximum, returns \c MaxEditDistance+1.
|
||||
///
|
||||
/// \returns the minimum number of character insertions, removals,
|
||||
/// or (if \p AllowReplacements is \c true) replacements needed to
|
||||
/// transform one of the given strings into the other. If zero,
|
||||
/// the strings are identical.
|
||||
unsigned edit_distance(StringRef Other, bool AllowReplacements = true,
|
||||
unsigned MaxEditDistance = 0) const;
|
||||
|
||||
/// str - Get the contents as an std::string.
|
||||
std::string str() const {
|
||||
if (!Data) return std::string();
|
||||
return std::string(Data, Length);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Operator Overloads
|
||||
/// @{
|
||||
|
||||
char operator[](size_t Index) const {
|
||||
assert(Index < Length && "Invalid index!");
|
||||
return Data[Index];
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Type Conversions
|
||||
/// @{
|
||||
|
||||
operator std::string() const {
|
||||
return str();
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name String Predicates
|
||||
/// @{
|
||||
|
||||
/// Check if this string starts with the given \p Prefix.
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
bool startswith(StringRef Prefix) const {
|
||||
return Length >= Prefix.Length &&
|
||||
compareMemory(Data, Prefix.Data, Prefix.Length) == 0;
|
||||
}
|
||||
|
||||
/// Check if this string starts with the given \p Prefix, ignoring case.
|
||||
bool startswith_lower(StringRef Prefix) const;
|
||||
|
||||
/// Check if this string ends with the given \p Suffix.
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
bool endswith(StringRef Suffix) const {
|
||||
return Length >= Suffix.Length &&
|
||||
compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0;
|
||||
}
|
||||
|
||||
/// Check if this string ends with the given \p Suffix, ignoring case.
|
||||
bool endswith_lower(StringRef Suffix) const;
|
||||
|
||||
/// @}
|
||||
/// @name String Searching
|
||||
/// @{
|
||||
|
||||
/// Search for the first character \p C in the string.
|
||||
///
|
||||
/// \returns The index of the first occurrence of \p C, or npos if not
|
||||
/// found.
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
size_t find(char C, size_t From = 0) const {
|
||||
size_t FindBegin = std::min(From, Length);
|
||||
if (FindBegin < Length) { // Avoid calling memchr with nullptr.
|
||||
// Just forward to memchr, which is faster than a hand-rolled loop.
|
||||
if (const void *P = ::memchr(Data + FindBegin, C, Length - FindBegin))
|
||||
return (size_t)(static_cast<const char *>(P) - Data);
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
/// Search for the first string \p Str in the string.
|
||||
///
|
||||
/// \returns The index of the first occurrence of \p Str, or npos if not
|
||||
/// found.
|
||||
size_t find(StringRef Str, size_t From = 0) const;
|
||||
|
||||
/// Search for the last character \p C in the string.
|
||||
///
|
||||
/// \returns The index of the last occurrence of \p C, or npos if not
|
||||
/// found.
|
||||
size_t rfind(char C, size_t From = npos) const {
|
||||
From = std::min(From, Length);
|
||||
size_t i = From;
|
||||
while (i != 0) {
|
||||
--i;
|
||||
if (Data[i] == C)
|
||||
return i;
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
/// Search for the last string \p Str in the string.
|
||||
///
|
||||
/// \returns The index of the last occurrence of \p Str, or npos if not
|
||||
/// found.
|
||||
size_t rfind(StringRef Str) const;
|
||||
|
||||
/// Find the first character in the string that is \p C, or npos if not
|
||||
/// found. Same as find.
|
||||
size_t find_first_of(char C, size_t From = 0) const {
|
||||
return find(C, From);
|
||||
}
|
||||
|
||||
/// Find the first character in the string that is in \p Chars, or npos if
|
||||
/// not found.
|
||||
///
|
||||
/// Complexity: O(size() + Chars.size())
|
||||
size_t find_first_of(StringRef Chars, size_t From = 0) const;
|
||||
|
||||
/// Find the first character in the string that is not \p C or npos if not
|
||||
/// found.
|
||||
size_t find_first_not_of(char C, size_t From = 0) const;
|
||||
|
||||
/// Find the first character in the string that is not in the string
|
||||
/// \p Chars, or npos if not found.
|
||||
///
|
||||
/// Complexity: O(size() + Chars.size())
|
||||
size_t find_first_not_of(StringRef Chars, size_t From = 0) const;
|
||||
|
||||
/// Find the last character in the string that is \p C, or npos if not
|
||||
/// found.
|
||||
size_t find_last_of(char C, size_t From = npos) const {
|
||||
return rfind(C, From);
|
||||
}
|
||||
|
||||
/// Find the last character in the string that is in \p C, or npos if not
|
||||
/// found.
|
||||
///
|
||||
/// Complexity: O(size() + Chars.size())
|
||||
size_t find_last_of(StringRef Chars, size_t From = npos) const;
|
||||
|
||||
/// Find the last character in the string that is not \p C, or npos if not
|
||||
/// found.
|
||||
size_t find_last_not_of(char C, size_t From = npos) const;
|
||||
|
||||
/// Find the last character in the string that is not in \p Chars, or
|
||||
/// npos if not found.
|
||||
///
|
||||
/// Complexity: O(size() + Chars.size())
|
||||
size_t find_last_not_of(StringRef Chars, size_t From = npos) const;
|
||||
|
||||
/// @}
|
||||
/// @name Helpful Algorithms
|
||||
/// @{
|
||||
|
||||
/// Return the number of occurrences of \p C in the string.
|
||||
size_t count(char C) const {
|
||||
size_t Count = 0;
|
||||
for (size_t i = 0, e = Length; i != e; ++i)
|
||||
if (Data[i] == C)
|
||||
++Count;
|
||||
return Count;
|
||||
}
|
||||
|
||||
/// Return the number of non-overlapped occurrences of \p Str in
|
||||
/// the string.
|
||||
size_t count(StringRef Str) const;
|
||||
|
||||
/// Parse the current string as an integer of the specified radix. If
|
||||
/// \p Radix is specified as zero, this does radix autosensing using
|
||||
/// extended C rules: 0 is octal, 0x is hex, 0b is binary.
|
||||
///
|
||||
/// If the string is invalid or if only a subset of the string is valid,
|
||||
/// this returns true to signify the error. The string is considered
|
||||
/// erroneous if empty or if it overflows T.
|
||||
template <typename T>
|
||||
typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type
|
||||
getAsInteger(unsigned Radix, T &Result) const {
|
||||
long long LLVal;
|
||||
if (getAsSignedInteger(*this, Radix, LLVal) ||
|
||||
static_cast<T>(LLVal) != LLVal)
|
||||
return true;
|
||||
Result = LLVal;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type
|
||||
getAsInteger(unsigned Radix, T &Result) const {
|
||||
unsigned long long ULLVal;
|
||||
// The additional cast to unsigned long long is required to avoid the
|
||||
// Visual C++ warning C4805: '!=' : unsafe mix of type 'bool' and type
|
||||
// 'unsigned __int64' when instantiating getAsInteger with T = bool.
|
||||
if (getAsUnsignedInteger(*this, Radix, ULLVal) ||
|
||||
static_cast<unsigned long long>(static_cast<T>(ULLVal)) != ULLVal)
|
||||
return true;
|
||||
Result = ULLVal;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Parse the current string as an integer of the specified \p Radix, or of
|
||||
/// an autosensed radix if the \p Radix given is 0. The current value in
|
||||
/// \p Result is discarded, and the storage is changed to be wide enough to
|
||||
/// store the parsed integer.
|
||||
///
|
||||
/// \returns true if the string does not solely consist of a valid
|
||||
/// non-empty number in the appropriate base.
|
||||
///
|
||||
/// APInt::fromString is superficially similar but assumes the
|
||||
/// string is well-formed in the given radix.
|
||||
bool getAsInteger(unsigned Radix, APInt &Result) const;
|
||||
|
||||
/// @}
|
||||
/// @name String Operations
|
||||
/// @{
|
||||
|
||||
// Convert the given ASCII string to lowercase.
|
||||
std::string lower() const;
|
||||
|
||||
/// Convert the given ASCII string to uppercase.
|
||||
std::string upper() const;
|
||||
|
||||
/// @}
|
||||
/// @name Substring Operations
|
||||
/// @{
|
||||
|
||||
/// Return a reference to the substring from [Start, Start + N).
|
||||
///
|
||||
/// \param Start The index of the starting character in the substring; if
|
||||
/// the index is npos or greater than the length of the string then the
|
||||
/// empty substring will be returned.
|
||||
///
|
||||
/// \param N The number of characters to included in the substring. If N
|
||||
/// exceeds the number of characters remaining in the string, the string
|
||||
/// suffix (starting with \p Start) will be returned.
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
StringRef substr(size_t Start, size_t N = npos) const {
|
||||
Start = std::min(Start, Length);
|
||||
return StringRef(Data + Start, std::min(N, Length - Start));
|
||||
}
|
||||
|
||||
/// Return a StringRef equal to 'this' but with the first \p N elements
|
||||
/// dropped.
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
StringRef drop_front(size_t N = 1) const {
|
||||
assert(size() >= N && "Dropping more elements than exist");
|
||||
return substr(N);
|
||||
}
|
||||
|
||||
/// Return a StringRef equal to 'this' but with the last \p N elements
|
||||
/// dropped.
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
StringRef drop_back(size_t N = 1) const {
|
||||
assert(size() >= N && "Dropping more elements than exist");
|
||||
return substr(0, size()-N);
|
||||
}
|
||||
|
||||
/// Return a reference to the substring from [Start, End).
|
||||
///
|
||||
/// \param Start The index of the starting character in the substring; if
|
||||
/// the index is npos or greater than the length of the string then the
|
||||
/// empty substring will be returned.
|
||||
///
|
||||
/// \param End The index following the last character to include in the
|
||||
/// substring. If this is npos, or less than \p Start, or exceeds the
|
||||
/// number of characters remaining in the string, the string suffix
|
||||
/// (starting with \p Start) will be returned.
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
StringRef slice(size_t Start, size_t End) const {
|
||||
Start = std::min(Start, Length);
|
||||
End = std::min(std::max(Start, End), Length);
|
||||
return StringRef(Data + Start, End - Start);
|
||||
}
|
||||
|
||||
/// Split into two substrings around the first occurrence of a separator
|
||||
/// character.
|
||||
///
|
||||
/// If \p Separator is in the string, then the result is a pair (LHS, RHS)
|
||||
/// such that (*this == LHS + Separator + RHS) is true and RHS is
|
||||
/// maximal. If \p Separator is not in the string, then the result is a
|
||||
/// pair (LHS, RHS) where (*this == LHS) and (RHS == "").
|
||||
///
|
||||
/// \param Separator The character to split on.
|
||||
/// \returns The split substrings.
|
||||
std::pair<StringRef, StringRef> split(char Separator) const {
|
||||
size_t Idx = find(Separator);
|
||||
if (Idx == npos)
|
||||
return std::make_pair(*this, StringRef());
|
||||
return std::make_pair(slice(0, Idx), slice(Idx+1, npos));
|
||||
}
|
||||
|
||||
/// Split into two substrings around the first occurrence of a separator
|
||||
/// string.
|
||||
///
|
||||
/// If \p Separator is in the string, then the result is a pair (LHS, RHS)
|
||||
/// such that (*this == LHS + Separator + RHS) is true and RHS is
|
||||
/// maximal. If \p Separator is not in the string, then the result is a
|
||||
/// pair (LHS, RHS) where (*this == LHS) and (RHS == "").
|
||||
///
|
||||
/// \param Separator - The string to split on.
|
||||
/// \return - The split substrings.
|
||||
std::pair<StringRef, StringRef> split(StringRef Separator) const {
|
||||
size_t Idx = find(Separator);
|
||||
if (Idx == npos)
|
||||
return std::make_pair(*this, StringRef());
|
||||
return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos));
|
||||
}
|
||||
|
||||
/// Split into substrings around the occurrences of a separator string.
|
||||
///
|
||||
/// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most
|
||||
/// \p MaxSplit splits are done and consequently <= \p MaxSplit + 1
|
||||
/// elements are added to A.
|
||||
/// If \p KeepEmpty is false, empty strings are not added to \p A. They
|
||||
/// still count when considering \p MaxSplit
|
||||
/// An useful invariant is that
|
||||
/// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true
|
||||
///
|
||||
/// \param A - Where to put the substrings.
|
||||
/// \param Separator - The string to split on.
|
||||
/// \param MaxSplit - The maximum number of times the string is split.
|
||||
/// \param KeepEmpty - True if empty substring should be added.
|
||||
void split(SmallVectorImpl<StringRef> &A,
|
||||
StringRef Separator, int MaxSplit = -1,
|
||||
bool KeepEmpty = true) const;
|
||||
|
||||
/// Split into substrings around the occurrences of a separator character.
|
||||
///
|
||||
/// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most
|
||||
/// \p MaxSplit splits are done and consequently <= \p MaxSplit + 1
|
||||
/// elements are added to A.
|
||||
/// If \p KeepEmpty is false, empty strings are not added to \p A. They
|
||||
/// still count when considering \p MaxSplit
|
||||
/// An useful invariant is that
|
||||
/// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true
|
||||
///
|
||||
/// \param A - Where to put the substrings.
|
||||
/// \param Separator - The string to split on.
|
||||
/// \param MaxSplit - The maximum number of times the string is split.
|
||||
/// \param KeepEmpty - True if empty substring should be added.
|
||||
void split(SmallVectorImpl<StringRef> &A, char Separator, int MaxSplit = -1,
|
||||
bool KeepEmpty = true) const;
|
||||
|
||||
/// Split into two substrings around the last occurrence of a separator
|
||||
/// character.
|
||||
///
|
||||
/// If \p Separator is in the string, then the result is a pair (LHS, RHS)
|
||||
/// such that (*this == LHS + Separator + RHS) is true and RHS is
|
||||
/// minimal. If \p Separator is not in the string, then the result is a
|
||||
/// pair (LHS, RHS) where (*this == LHS) and (RHS == "").
|
||||
///
|
||||
/// \param Separator - The character to split on.
|
||||
/// \return - The split substrings.
|
||||
std::pair<StringRef, StringRef> rsplit(char Separator) const {
|
||||
size_t Idx = rfind(Separator);
|
||||
if (Idx == npos)
|
||||
return std::make_pair(*this, StringRef());
|
||||
return std::make_pair(slice(0, Idx), slice(Idx+1, npos));
|
||||
}
|
||||
|
||||
/// Return string with consecutive characters in \p Chars starting from
|
||||
/// the left removed.
|
||||
StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const {
|
||||
return drop_front(std::min(Length, find_first_not_of(Chars)));
|
||||
}
|
||||
|
||||
/// Return string with consecutive characters in \p Chars starting from
|
||||
/// the right removed.
|
||||
StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const {
|
||||
return drop_back(Length - std::min(Length, find_last_not_of(Chars) + 1));
|
||||
}
|
||||
|
||||
/// Return string with consecutive characters in \p Chars starting from
|
||||
/// the left and right removed.
|
||||
StringRef trim(StringRef Chars = " \t\n\v\f\r") const {
|
||||
return ltrim(Chars).rtrim(Chars);
|
||||
}
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
/// @name StringRef Comparison Operators
|
||||
/// @{
|
||||
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
inline bool operator==(StringRef LHS, StringRef RHS) {
|
||||
return LHS.equals(RHS);
|
||||
}
|
||||
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
inline bool operator!=(StringRef LHS, StringRef RHS) {
|
||||
return !(LHS == RHS);
|
||||
}
|
||||
|
||||
inline bool operator<(StringRef LHS, StringRef RHS) {
|
||||
return LHS.compare(RHS) == -1;
|
||||
}
|
||||
|
||||
inline bool operator<=(StringRef LHS, StringRef RHS) {
|
||||
return LHS.compare(RHS) != 1;
|
||||
}
|
||||
|
||||
inline bool operator>(StringRef LHS, StringRef RHS) {
|
||||
return LHS.compare(RHS) == 1;
|
||||
}
|
||||
|
||||
inline bool operator>=(StringRef LHS, StringRef RHS) {
|
||||
return LHS.compare(RHS) != -1;
|
||||
}
|
||||
|
||||
inline std::string &operator+=(std::string &buffer, StringRef string) {
|
||||
return buffer.append(string.data(), string.size());
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \brief Compute a hash_code for a StringRef.
|
||||
hash_code hash_value(StringRef S);
|
||||
|
||||
// StringRefs can be treated like a POD type.
|
||||
template <typename T> struct isPodLike;
|
||||
template <> struct isPodLike<StringRef> { static const bool value = true; };
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,87 @@
|
||||
//===--- Strings.h - Shared string constants across components --*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_STRINGS_H
|
||||
#define SWIFT_STRINGS_H
|
||||
|
||||
#include "LLVM.h"
|
||||
#include "StringRef.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
/// The name of the standard library, which is a reserved module name.
|
||||
constexpr static const char STDLIB_NAME[] = "Swift";
|
||||
/// The name of the Onone support library, which is a reserved module name.
|
||||
constexpr static const char SWIFT_ONONE_SUPPORT[] = "SwiftOnoneSupport";
|
||||
/// The name of the SwiftShims module, which contains private stdlib decls.
|
||||
constexpr static const char SWIFT_SHIMS_NAME[] = "SwiftShims";
|
||||
/// The name of the Builtin module, which contains Builtin functions.
|
||||
constexpr static const char BUILTIN_NAME[] = "Builtin";
|
||||
/// The prefix of module names used by LLDB to capture Swift expressions
|
||||
constexpr static const char LLDB_EXPRESSIONS_MODULE_NAME_PREFIX[] =
|
||||
"__lldb_expr_";
|
||||
|
||||
/// The name of the fake module used to hold imported Objective-C things.
|
||||
constexpr static const char MANGLING_MODULE_OBJC[] = "__C";
|
||||
/// The name of the fake module used to hold synthesized ClangImporter things.
|
||||
constexpr static const char MANGLING_MODULE_CLANG_IMPORTER[] =
|
||||
"__C_Synthesized";
|
||||
|
||||
/// The name of the Builtin type prefix
|
||||
constexpr static const char BUILTIN_TYPE_NAME_PREFIX[] = "Builtin.";
|
||||
/// The name of the Builtin type for Int
|
||||
constexpr static const char BUILTIN_TYPE_NAME_INT[] = "Builtin.Int";
|
||||
/// The name of the Builtin type for Int8
|
||||
constexpr static const char BUILTIN_TYPE_NAME_INT8[] = "Builtin.Int8";
|
||||
/// The name of the Builtin type for Int16
|
||||
constexpr static const char BUILTIN_TYPE_NAME_INT16[] = "Builtin.Int16";
|
||||
/// The name of the Builtin type for Int32
|
||||
constexpr static const char BUILTIN_TYPE_NAME_INT32[] = "Builtin.Int32";
|
||||
/// The name of the Builtin type for Int64
|
||||
constexpr static const char BUILTIN_TYPE_NAME_INT64[] = "Builtin.Int64";
|
||||
/// The name of the Builtin type for Int128
|
||||
constexpr static const char BUILTIN_TYPE_NAME_INT128[] = "Builtin.Int128";
|
||||
/// The name of the Builtin type for Int256
|
||||
constexpr static const char BUILTIN_TYPE_NAME_INT256[] = "Builtin.Int256";
|
||||
/// The name of the Builtin type for Int512
|
||||
constexpr static const char BUILTIN_TYPE_NAME_INT512[] = "Builtin.Int512";
|
||||
/// The name of the Builtin type for IntLiteral
|
||||
constexpr static const char BUILTIN_TYPE_NAME_INTLITERAL[] =
|
||||
"Builtin.IntLiteral";
|
||||
/// The name of the Builtin type for Float
|
||||
constexpr static const char BUILTIN_TYPE_NAME_FLOAT[] = "Builtin.FPIEEE";
|
||||
/// The name of the Builtin type for NativeObject
|
||||
constexpr static const char BUILTIN_TYPE_NAME_NATIVEOBJECT[] =
|
||||
"Builtin.NativeObject";
|
||||
/// The name of the Builtin type for BridgeObject
|
||||
constexpr static const char BUILTIN_TYPE_NAME_BRIDGEOBJECT[] =
|
||||
"Builtin.BridgeObject";
|
||||
/// The name of the Builtin type for RawPointer
|
||||
constexpr static const char BUILTIN_TYPE_NAME_RAWPOINTER[] =
|
||||
"Builtin.RawPointer";
|
||||
/// The name of the Builtin type for UnsafeValueBuffer
|
||||
constexpr static const char BUILTIN_TYPE_NAME_UNSAFEVALUEBUFFER[] =
|
||||
"Builtin.UnsafeValueBuffer";
|
||||
/// The name of the Builtin type for UnknownObject
|
||||
constexpr static const char BUILTIN_TYPE_NAME_UNKNOWNOBJECT[] =
|
||||
"Builtin.UnknownObject";
|
||||
/// The name of the Builtin type for Vector
|
||||
constexpr static const char BUILTIN_TYPE_NAME_VEC[] = "Builtin.Vec";
|
||||
/// The name of the Builtin type for SILToken
|
||||
constexpr static const char BUILTIN_TYPE_NAME_SILTOKEN[] = "Builtin.SILToken";
|
||||
/// The name of the Builtin type for Word
|
||||
constexpr static const char BUILTIN_TYPE_NAME_WORD[] = "Builtin.Word";
|
||||
// constexpr static StringLiteral SEMANTICS_PROGRAMTERMINATION_POINT =
|
||||
// "programtermination_point";
|
||||
} // end namespace swift
|
||||
|
||||
#endif // SWIFT_STRINGS_H
|
||||
@@ -0,0 +1,108 @@
|
||||
/*===------- llvm/Config/llvm-config.h - llvm configuration -------*- C -*-===*/
|
||||
/* */
|
||||
/* The LLVM Compiler Infrastructure */
|
||||
/* */
|
||||
/* This file is distributed under the University of Illinois Open Source */
|
||||
/* License. See LICENSE.TXT for details. */
|
||||
/* */
|
||||
/*===----------------------------------------------------------------------===*/
|
||||
|
||||
/* This file enumerates variables from the LLVM configuration so that they
|
||||
can be in exported headers and won't override package specific directives.
|
||||
This is a C header that can be included in the llvm-c headers. */
|
||||
|
||||
#ifndef LLVM_CONFIG_H
|
||||
#define LLVM_CONFIG_H
|
||||
|
||||
/* Installation directory for binary executables */
|
||||
/* #undef LLVM_BINDIR */
|
||||
|
||||
/* Time at which LLVM was configured */
|
||||
/* #undef LLVM_CONFIGTIME */
|
||||
|
||||
/* Installation directory for data files */
|
||||
/* #undef LLVM_DATADIR */
|
||||
|
||||
/* Target triple LLVM will generate code for by default */
|
||||
#define LLVM_DEFAULT_TARGET_TRIPLE "x86_64-apple-darwin15.3.0"
|
||||
|
||||
/* Installation directory for documentation */
|
||||
/* #undef LLVM_DOCSDIR */
|
||||
|
||||
/* Define if LLVM is built with asserts and checks that change the layout of
|
||||
client-visible data structures. */
|
||||
/* #undef LLVM_ENABLE_ABI_BREAKING_CHECKS */
|
||||
|
||||
/* Define if threads enabled */
|
||||
#define LLVM_ENABLE_THREADS 1
|
||||
|
||||
/* Installation directory for config files */
|
||||
/* #undef LLVM_ETCDIR */
|
||||
|
||||
/* Has gcc/MSVC atomic intrinsics */
|
||||
#define LLVM_HAS_ATOMICS 1
|
||||
|
||||
/* Host triple LLVM will be executed on */
|
||||
#define LLVM_HOST_TRIPLE "x86_64-apple-darwin15.3.0"
|
||||
|
||||
/* Installation directory for include files */
|
||||
/* #undef LLVM_INCLUDEDIR */
|
||||
|
||||
/* Installation directory for .info files */
|
||||
/* #undef LLVM_INFODIR */
|
||||
|
||||
/* Installation directory for man pages */
|
||||
/* #undef LLVM_MANDIR */
|
||||
|
||||
/* LLVM architecture name for the native architecture, if available */
|
||||
#define LLVM_NATIVE_ARCH X86
|
||||
|
||||
/* LLVM name for the native AsmParser init function, if available */
|
||||
#define LLVM_NATIVE_ASMPARSER LLVMInitializeX86AsmParser
|
||||
|
||||
/* LLVM name for the native AsmPrinter init function, if available */
|
||||
#define LLVM_NATIVE_ASMPRINTER LLVMInitializeX86AsmPrinter
|
||||
|
||||
/* LLVM name for the native Disassembler init function, if available */
|
||||
#define LLVM_NATIVE_DISASSEMBLER LLVMInitializeX86Disassembler
|
||||
|
||||
/* LLVM name for the native Target init function, if available */
|
||||
#define LLVM_NATIVE_TARGET LLVMInitializeX86Target
|
||||
|
||||
/* LLVM name for the native TargetInfo init function, if available */
|
||||
#define LLVM_NATIVE_TARGETINFO LLVMInitializeX86TargetInfo
|
||||
|
||||
/* LLVM name for the native target MC init function, if available */
|
||||
#define LLVM_NATIVE_TARGETMC LLVMInitializeX86TargetMC
|
||||
|
||||
/* Define if this is Unixish platform */
|
||||
#define LLVM_ON_UNIX 1
|
||||
|
||||
/* Define if this is Win32ish platform */
|
||||
/* #undef LLVM_ON_WIN32 */
|
||||
|
||||
/* Installation prefix directory */
|
||||
#define LLVM_PREFIX "/usr/local"
|
||||
|
||||
/* Define if we have the Intel JIT API runtime support library */
|
||||
/* #undef LLVM_USE_INTEL_JITEVENTS */
|
||||
|
||||
/* Define if we have the oprofile JIT-support library */
|
||||
/* #undef LLVM_USE_OPROFILE */
|
||||
|
||||
/* Major version of the LLVM API */
|
||||
#define LLVM_VERSION_MAJOR 3
|
||||
|
||||
/* Minor version of the LLVM API */
|
||||
#define LLVM_VERSION_MINOR 9
|
||||
|
||||
/* Patch version of the LLVM API */
|
||||
#define LLVM_VERSION_PATCH 0
|
||||
|
||||
/* LLVM version string */
|
||||
#define LLVM_VERSION_STRING "3.9.0svn"
|
||||
|
||||
/* Define if we link Polly to the tools */
|
||||
/* #undef LINK_POLLY_INTO_TOOLS */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,109 @@
|
||||
//===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides useful additions to the standard type_traits library.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_TYPE_TRAITS_H
|
||||
#define LLVM_SUPPORT_TYPE_TRAITS_H
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#ifndef __has_feature
|
||||
#define LLVM_DEFINED_HAS_FEATURE
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// isPodLike - This is a type trait that is used to determine whether a given
|
||||
/// type can be copied around with memcpy instead of running ctors etc.
|
||||
template <typename T>
|
||||
struct isPodLike {
|
||||
// std::is_trivially_copyable is available in libc++ with clang, libstdc++
|
||||
// that comes with GCC 5.
|
||||
#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \
|
||||
(defined(__GNUC__) && __GNUC__ >= 5)
|
||||
// If the compiler supports the is_trivially_copyable trait use it, as it
|
||||
// matches the definition of isPodLike closely.
|
||||
static const bool value = std::is_trivially_copyable<T>::value;
|
||||
#elif __has_feature(is_trivially_copyable)
|
||||
// Use the internal name if the compiler supports is_trivially_copyable but we
|
||||
// don't know if the standard library does. This is the case for clang in
|
||||
// conjunction with libstdc++ from GCC 4.x.
|
||||
static const bool value = __is_trivially_copyable(T);
|
||||
#else
|
||||
// If we don't know anything else, we can (at least) assume that all non-class
|
||||
// types are PODs.
|
||||
static const bool value = !std::is_class<T>::value;
|
||||
#endif
|
||||
};
|
||||
|
||||
// std::pair's are pod-like if their elements are.
|
||||
template<typename T, typename U>
|
||||
struct isPodLike<std::pair<T, U> > {
|
||||
static const bool value = isPodLike<T>::value && isPodLike<U>::value;
|
||||
};
|
||||
|
||||
/// \brief Metafunction that determines whether the given type is either an
|
||||
/// integral type or an enumeration type.
|
||||
///
|
||||
/// Note that this accepts potentially more integral types than is_integral
|
||||
/// because it is based on merely being convertible implicitly to an integral
|
||||
/// type.
|
||||
template <typename T> class is_integral_or_enum {
|
||||
typedef typename std::remove_reference<T>::type UnderlyingT;
|
||||
|
||||
public:
|
||||
static const bool value =
|
||||
!std::is_class<UnderlyingT>::value && // Filter conversion operators.
|
||||
!std::is_pointer<UnderlyingT>::value &&
|
||||
!std::is_floating_point<UnderlyingT>::value &&
|
||||
std::is_convertible<UnderlyingT, unsigned long long>::value;
|
||||
};
|
||||
|
||||
/// \brief If T is a pointer, just return it. If it is not, return T&.
|
||||
template<typename T, typename Enable = void>
|
||||
struct add_lvalue_reference_if_not_pointer { typedef T &type; };
|
||||
|
||||
template <typename T>
|
||||
struct add_lvalue_reference_if_not_pointer<
|
||||
T, typename std::enable_if<std::is_pointer<T>::value>::type> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
/// \brief If T is a pointer to X, return a pointer to const X. If it is not,
|
||||
/// return const T.
|
||||
template<typename T, typename Enable = void>
|
||||
struct add_const_past_pointer { typedef const T type; };
|
||||
|
||||
template <typename T>
|
||||
struct add_const_past_pointer<
|
||||
T, typename std::enable_if<std::is_pointer<T>::value>::type> {
|
||||
typedef const typename std::remove_pointer<T>::type *type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// If the compiler supports detecting whether a class is final, define
|
||||
// an LLVM_IS_FINAL macro. If it cannot be defined properly, this
|
||||
// macro will be left undefined.
|
||||
#if __cplusplus >= 201402L
|
||||
#define LLVM_IS_FINAL(Ty) std::is_final<Ty>()
|
||||
#elif __has_feature(is_final) || LLVM_GNUC_PREREQ(4, 7, 0)
|
||||
#define LLVM_IS_FINAL(Ty) __is_final(Ty)
|
||||
#endif
|
||||
|
||||
#ifdef LLVM_DEFINED_HAS_FEATURE
|
||||
#undef __has_feature
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// MASCompositeConstraint.h
|
||||
// Masonry
|
||||
//
|
||||
// Created by Jonas Budelmann on 21/07/13.
|
||||
// Copyright (c) 2013 cloudling. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MASConstraint.h"
|
||||
#import "MASUtilities.h"
|
||||
|
||||
/**
|
||||
* A group of MASConstraint objects
|
||||
*/
|
||||
@interface MASCompositeConstraint : MASConstraint
|
||||
|
||||
/**
|
||||
* Creates a composite with a predefined array of children
|
||||
*
|
||||
* @param children child MASConstraints
|
||||
*
|
||||
* @return a composite constraint
|
||||
*/
|
||||
- (id)initWithChildren:(NSArray *)children;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// MASConstraint+Private.h
|
||||
// Masonry
|
||||
//
|
||||
// Created by Nick Tymchenko on 29/04/14.
|
||||
// Copyright (c) 2014 cloudling. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MASConstraint.h"
|
||||
|
||||
@protocol MASConstraintDelegate;
|
||||
|
||||
|
||||
@interface MASConstraint ()
|
||||
|
||||
/**
|
||||
* Whether or not to check for an existing constraint instead of adding constraint
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL updateExisting;
|
||||
|
||||
/**
|
||||
* Usually MASConstraintMaker but could be a parent MASConstraint
|
||||
*/
|
||||
@property (nonatomic, weak) id<MASConstraintDelegate> delegate;
|
||||
|
||||
/**
|
||||
* Based on a provided value type, is equal to calling:
|
||||
* NSNumber - setOffset:
|
||||
* NSValue with CGPoint - setPointOffset:
|
||||
* NSValue with CGSize - setSizeOffset:
|
||||
* NSValue with MASEdgeInsets - setInsets:
|
||||
*/
|
||||
- (void)setLayoutConstantWithValue:(NSValue *)value;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface MASConstraint (Abstract)
|
||||
|
||||
/**
|
||||
* Sets the constraint relation to given NSLayoutRelation
|
||||
* returns a block which accepts one of the following:
|
||||
* MASViewAttribute, UIView, NSValue, NSArray
|
||||
* see readme for more details.
|
||||
*/
|
||||
- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation;
|
||||
|
||||
/**
|
||||
* Override to set a custom chaining behaviour
|
||||
*/
|
||||
- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@protocol MASConstraintDelegate <NSObject>
|
||||
|
||||
/**
|
||||
* Notifies the delegate when the constraint needs to be replaced with another constraint. For example
|
||||
* A MASViewConstraint may turn into a MASCompositeConstraint when an array is passed to one of the equality blocks
|
||||
*/
|
||||
- (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint;
|
||||
|
||||
- (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,272 @@
|
||||
//
|
||||
// MASConstraint.h
|
||||
// Masonry
|
||||
//
|
||||
// Created by Jonas Budelmann on 22/07/13.
|
||||
// Copyright (c) 2013 cloudling. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MASUtilities.h"
|
||||
|
||||
/**
|
||||
* Enables Constraints to be created with chainable syntax
|
||||
* Constraint can represent single NSLayoutConstraint (MASViewConstraint)
|
||||
* or a group of NSLayoutConstraints (MASComposisteConstraint)
|
||||
*/
|
||||
@interface MASConstraint : NSObject
|
||||
|
||||
// Chaining Support
|
||||
|
||||
/**
|
||||
* Modifies the NSLayoutConstraint constant,
|
||||
* only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
|
||||
* NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight
|
||||
*/
|
||||
- (MASConstraint * (^)(MASEdgeInsets insets))insets;
|
||||
|
||||
/**
|
||||
* Modifies the NSLayoutConstraint constant,
|
||||
* only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
|
||||
* NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight
|
||||
*/
|
||||
- (MASConstraint * (^)(CGFloat inset))inset;
|
||||
|
||||
/**
|
||||
* Modifies the NSLayoutConstraint constant,
|
||||
* only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
|
||||
* NSLayoutAttributeWidth, NSLayoutAttributeHeight
|
||||
*/
|
||||
- (MASConstraint * (^)(CGSize offset))sizeOffset;
|
||||
|
||||
/**
|
||||
* Modifies the NSLayoutConstraint constant,
|
||||
* only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
|
||||
* NSLayoutAttributeCenterX, NSLayoutAttributeCenterY
|
||||
*/
|
||||
- (MASConstraint * (^)(CGPoint offset))centerOffset;
|
||||
|
||||
/**
|
||||
* Modifies the NSLayoutConstraint constant
|
||||
*/
|
||||
- (MASConstraint * (^)(CGFloat offset))offset;
|
||||
|
||||
/**
|
||||
* Modifies the NSLayoutConstraint constant based on a value type
|
||||
*/
|
||||
- (MASConstraint * (^)(NSValue *value))valueOffset;
|
||||
|
||||
/**
|
||||
* Sets the NSLayoutConstraint multiplier property
|
||||
*/
|
||||
- (MASConstraint * (^)(CGFloat multiplier))multipliedBy;
|
||||
|
||||
/**
|
||||
* Sets the NSLayoutConstraint multiplier to 1.0/dividedBy
|
||||
*/
|
||||
- (MASConstraint * (^)(CGFloat divider))dividedBy;
|
||||
|
||||
/**
|
||||
* Sets the NSLayoutConstraint priority to a float or MASLayoutPriority
|
||||
*/
|
||||
- (MASConstraint * (^)(MASLayoutPriority priority))priority;
|
||||
|
||||
/**
|
||||
* Sets the NSLayoutConstraint priority to MASLayoutPriorityLow
|
||||
*/
|
||||
- (MASConstraint * (^)(void))priorityLow;
|
||||
|
||||
/**
|
||||
* Sets the NSLayoutConstraint priority to MASLayoutPriorityMedium
|
||||
*/
|
||||
- (MASConstraint * (^)(void))priorityMedium;
|
||||
|
||||
/**
|
||||
* Sets the NSLayoutConstraint priority to MASLayoutPriorityHigh
|
||||
*/
|
||||
- (MASConstraint * (^)(void))priorityHigh;
|
||||
|
||||
/**
|
||||
* Sets the constraint relation to NSLayoutRelationEqual
|
||||
* returns a block which accepts one of the following:
|
||||
* MASViewAttribute, UIView, NSValue, NSArray
|
||||
* see readme for more details.
|
||||
*/
|
||||
- (MASConstraint * (^)(id attr))equalTo;
|
||||
|
||||
/**
|
||||
* Sets the constraint relation to NSLayoutRelationGreaterThanOrEqual
|
||||
* returns a block which accepts one of the following:
|
||||
* MASViewAttribute, UIView, NSValue, NSArray
|
||||
* see readme for more details.
|
||||
*/
|
||||
- (MASConstraint * (^)(id attr))greaterThanOrEqualTo;
|
||||
|
||||
/**
|
||||
* Sets the constraint relation to NSLayoutRelationLessThanOrEqual
|
||||
* returns a block which accepts one of the following:
|
||||
* MASViewAttribute, UIView, NSValue, NSArray
|
||||
* see readme for more details.
|
||||
*/
|
||||
- (MASConstraint * (^)(id attr))lessThanOrEqualTo;
|
||||
|
||||
/**
|
||||
* Optional semantic property which has no effect but improves the readability of constraint
|
||||
*/
|
||||
- (MASConstraint *)with;
|
||||
|
||||
/**
|
||||
* Optional semantic property which has no effect but improves the readability of constraint
|
||||
*/
|
||||
- (MASConstraint *)and;
|
||||
|
||||
/**
|
||||
* Creates a new MASCompositeConstraint with the called attribute and reciever
|
||||
*/
|
||||
- (MASConstraint *)left;
|
||||
- (MASConstraint *)top;
|
||||
- (MASConstraint *)right;
|
||||
- (MASConstraint *)bottom;
|
||||
- (MASConstraint *)leading;
|
||||
- (MASConstraint *)trailing;
|
||||
- (MASConstraint *)width;
|
||||
- (MASConstraint *)height;
|
||||
- (MASConstraint *)centerX;
|
||||
- (MASConstraint *)centerY;
|
||||
- (MASConstraint *)baseline;
|
||||
|
||||
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
|
||||
|
||||
- (MASConstraint *)firstBaseline;
|
||||
- (MASConstraint *)lastBaseline;
|
||||
|
||||
#endif
|
||||
|
||||
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
|
||||
|
||||
- (MASConstraint *)leftMargin;
|
||||
- (MASConstraint *)rightMargin;
|
||||
- (MASConstraint *)topMargin;
|
||||
- (MASConstraint *)bottomMargin;
|
||||
- (MASConstraint *)leadingMargin;
|
||||
- (MASConstraint *)trailingMargin;
|
||||
- (MASConstraint *)centerXWithinMargins;
|
||||
- (MASConstraint *)centerYWithinMargins;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Sets the constraint debug name
|
||||
*/
|
||||
- (MASConstraint * (^)(id key))key;
|
||||
|
||||
// NSLayoutConstraint constant Setters
|
||||
// for use outside of mas_updateConstraints/mas_makeConstraints blocks
|
||||
|
||||
/**
|
||||
* Modifies the NSLayoutConstraint constant,
|
||||
* only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
|
||||
* NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight
|
||||
*/
|
||||
- (void)setInsets:(MASEdgeInsets)insets;
|
||||
|
||||
/**
|
||||
* Modifies the NSLayoutConstraint constant,
|
||||
* only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
|
||||
* NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight
|
||||
*/
|
||||
- (void)setInset:(CGFloat)inset;
|
||||
|
||||
/**
|
||||
* Modifies the NSLayoutConstraint constant,
|
||||
* only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
|
||||
* NSLayoutAttributeWidth, NSLayoutAttributeHeight
|
||||
*/
|
||||
- (void)setSizeOffset:(CGSize)sizeOffset;
|
||||
|
||||
/**
|
||||
* Modifies the NSLayoutConstraint constant,
|
||||
* only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
|
||||
* NSLayoutAttributeCenterX, NSLayoutAttributeCenterY
|
||||
*/
|
||||
- (void)setCenterOffset:(CGPoint)centerOffset;
|
||||
|
||||
/**
|
||||
* Modifies the NSLayoutConstraint constant
|
||||
*/
|
||||
- (void)setOffset:(CGFloat)offset;
|
||||
|
||||
|
||||
// NSLayoutConstraint Installation support
|
||||
|
||||
#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV)
|
||||
/**
|
||||
* Whether or not to go through the animator proxy when modifying the constraint
|
||||
*/
|
||||
@property (nonatomic, copy, readonly) MASConstraint *animator;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Activates an NSLayoutConstraint if it's supported by an OS.
|
||||
* Invokes install otherwise.
|
||||
*/
|
||||
- (void)activate;
|
||||
|
||||
/**
|
||||
* Deactivates previously installed/activated NSLayoutConstraint.
|
||||
*/
|
||||
- (void)deactivate;
|
||||
|
||||
/**
|
||||
* Creates a NSLayoutConstraint and adds it to the appropriate view.
|
||||
*/
|
||||
- (void)install;
|
||||
|
||||
/**
|
||||
* Removes previously installed NSLayoutConstraint
|
||||
*/
|
||||
- (void)uninstall;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
* Convenience auto-boxing macros for MASConstraint methods.
|
||||
*
|
||||
* Defining MAS_SHORTHAND_GLOBALS will turn on auto-boxing for default syntax.
|
||||
* A potential drawback of this is that the unprefixed macros will appear in global scope.
|
||||
*/
|
||||
#define mas_equalTo(...) equalTo(MASBoxValue((__VA_ARGS__)))
|
||||
#define mas_greaterThanOrEqualTo(...) greaterThanOrEqualTo(MASBoxValue((__VA_ARGS__)))
|
||||
#define mas_lessThanOrEqualTo(...) lessThanOrEqualTo(MASBoxValue((__VA_ARGS__)))
|
||||
|
||||
#define mas_offset(...) valueOffset(MASBoxValue((__VA_ARGS__)))
|
||||
|
||||
|
||||
#ifdef MAS_SHORTHAND_GLOBALS
|
||||
|
||||
#define equalTo(...) mas_equalTo(__VA_ARGS__)
|
||||
#define greaterThanOrEqualTo(...) mas_greaterThanOrEqualTo(__VA_ARGS__)
|
||||
#define lessThanOrEqualTo(...) mas_lessThanOrEqualTo(__VA_ARGS__)
|
||||
|
||||
#define offset(...) mas_offset(__VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@interface MASConstraint (AutoboxingSupport)
|
||||
|
||||
/**
|
||||
* Aliases to corresponding relation methods (for shorthand macros)
|
||||
* Also needed to aid autocompletion
|
||||
*/
|
||||
- (MASConstraint * (^)(id attr))mas_equalTo;
|
||||
- (MASConstraint * (^)(id attr))mas_greaterThanOrEqualTo;
|
||||
- (MASConstraint * (^)(id attr))mas_lessThanOrEqualTo;
|
||||
|
||||
/**
|
||||
* A dummy method to aid autocompletion
|
||||
*/
|
||||
- (MASConstraint * (^)(id offset))mas_offset;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,146 @@
|
||||
//
|
||||
// MASConstraintMaker.h
|
||||
// Masonry
|
||||
//
|
||||
// Created by Jonas Budelmann on 20/07/13.
|
||||
// Copyright (c) 2013 cloudling. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MASConstraint.h"
|
||||
#import "MASUtilities.h"
|
||||
|
||||
typedef NS_OPTIONS(NSInteger, MASAttribute) {
|
||||
MASAttributeLeft = 1 << NSLayoutAttributeLeft,
|
||||
MASAttributeRight = 1 << NSLayoutAttributeRight,
|
||||
MASAttributeTop = 1 << NSLayoutAttributeTop,
|
||||
MASAttributeBottom = 1 << NSLayoutAttributeBottom,
|
||||
MASAttributeLeading = 1 << NSLayoutAttributeLeading,
|
||||
MASAttributeTrailing = 1 << NSLayoutAttributeTrailing,
|
||||
MASAttributeWidth = 1 << NSLayoutAttributeWidth,
|
||||
MASAttributeHeight = 1 << NSLayoutAttributeHeight,
|
||||
MASAttributeCenterX = 1 << NSLayoutAttributeCenterX,
|
||||
MASAttributeCenterY = 1 << NSLayoutAttributeCenterY,
|
||||
MASAttributeBaseline = 1 << NSLayoutAttributeBaseline,
|
||||
|
||||
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
|
||||
|
||||
MASAttributeFirstBaseline = 1 << NSLayoutAttributeFirstBaseline,
|
||||
MASAttributeLastBaseline = 1 << NSLayoutAttributeLastBaseline,
|
||||
|
||||
#endif
|
||||
|
||||
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
|
||||
|
||||
MASAttributeLeftMargin = 1 << NSLayoutAttributeLeftMargin,
|
||||
MASAttributeRightMargin = 1 << NSLayoutAttributeRightMargin,
|
||||
MASAttributeTopMargin = 1 << NSLayoutAttributeTopMargin,
|
||||
MASAttributeBottomMargin = 1 << NSLayoutAttributeBottomMargin,
|
||||
MASAttributeLeadingMargin = 1 << NSLayoutAttributeLeadingMargin,
|
||||
MASAttributeTrailingMargin = 1 << NSLayoutAttributeTrailingMargin,
|
||||
MASAttributeCenterXWithinMargins = 1 << NSLayoutAttributeCenterXWithinMargins,
|
||||
MASAttributeCenterYWithinMargins = 1 << NSLayoutAttributeCenterYWithinMargins,
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides factory methods for creating MASConstraints.
|
||||
* Constraints are collected until they are ready to be installed
|
||||
*
|
||||
*/
|
||||
@interface MASConstraintMaker : NSObject
|
||||
|
||||
/**
|
||||
* The following properties return a new MASViewConstraint
|
||||
* with the first item set to the makers associated view and the appropriate MASViewAttribute
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) MASConstraint *left;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *top;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *right;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *bottom;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *leading;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *trailing;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *width;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *height;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *centerX;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *centerY;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *baseline;
|
||||
|
||||
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
|
||||
|
||||
@property (nonatomic, strong, readonly) MASConstraint *firstBaseline;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *lastBaseline;
|
||||
|
||||
#endif
|
||||
|
||||
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
|
||||
|
||||
@property (nonatomic, strong, readonly) MASConstraint *leftMargin;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *rightMargin;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *topMargin;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *bottomMargin;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *leadingMargin;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *trailingMargin;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *centerXWithinMargins;
|
||||
@property (nonatomic, strong, readonly) MASConstraint *centerYWithinMargins;
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns a block which creates a new MASCompositeConstraint with the first item set
|
||||
* to the makers associated view and children corresponding to the set bits in the
|
||||
* MASAttribute parameter. Combine multiple attributes via binary-or.
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) MASConstraint *(^attributes)(MASAttribute attrs);
|
||||
|
||||
/**
|
||||
* Creates a MASCompositeConstraint with type MASCompositeConstraintTypeEdges
|
||||
* which generates the appropriate MASViewConstraint children (top, left, bottom, right)
|
||||
* with the first item set to the makers associated view
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) MASConstraint *edges;
|
||||
|
||||
/**
|
||||
* Creates a MASCompositeConstraint with type MASCompositeConstraintTypeSize
|
||||
* which generates the appropriate MASViewConstraint children (width, height)
|
||||
* with the first item set to the makers associated view
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) MASConstraint *size;
|
||||
|
||||
/**
|
||||
* Creates a MASCompositeConstraint with type MASCompositeConstraintTypeCenter
|
||||
* which generates the appropriate MASViewConstraint children (centerX, centerY)
|
||||
* with the first item set to the makers associated view
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) MASConstraint *center;
|
||||
|
||||
/**
|
||||
* Whether or not to check for an existing constraint instead of adding constraint
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL updateExisting;
|
||||
|
||||
/**
|
||||
* Whether or not to remove existing constraints prior to installing
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL removeExisting;
|
||||
|
||||
/**
|
||||
* initialises the maker with a default view
|
||||
*
|
||||
* @param view any MASConstraint are created with this view as the first item
|
||||
*
|
||||
* @return a new MASConstraintMaker
|
||||
*/
|
||||
- (id)initWithView:(MAS_VIEW *)view;
|
||||
|
||||
/**
|
||||
* Calls install method on any MASConstraints which have been created by this maker
|
||||
*
|
||||
* @return an array of all the installed MASConstraints
|
||||
*/
|
||||
- (NSArray *)install;
|
||||
|
||||
- (MASConstraint * (^)(dispatch_block_t))group;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// MASLayoutConstraint.h
|
||||
// Masonry
|
||||
//
|
||||
// Created by Jonas Budelmann on 3/08/13.
|
||||
// Copyright (c) 2013 Jonas Budelmann. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MASUtilities.h"
|
||||
|
||||
/**
|
||||
* When you are debugging or printing the constraints attached to a view this subclass
|
||||
* makes it easier to identify which constraints have been created via Masonry
|
||||
*/
|
||||
@interface MASLayoutConstraint : NSLayoutConstraint
|
||||
|
||||
/**
|
||||
* a key to associate with this constraint
|
||||
*/
|
||||
@property (nonatomic, strong) id mas_key;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,136 @@
|
||||
//
|
||||
// MASUtilities.h
|
||||
// Masonry
|
||||
//
|
||||
// Created by Jonas Budelmann on 19/08/13.
|
||||
// Copyright (c) 2013 Jonas Budelmann. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_TV
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#define MAS_VIEW UIView
|
||||
#define MAS_VIEW_CONTROLLER UIViewController
|
||||
#define MASEdgeInsets UIEdgeInsets
|
||||
|
||||
typedef UILayoutPriority MASLayoutPriority;
|
||||
static const MASLayoutPriority MASLayoutPriorityRequired = UILayoutPriorityRequired;
|
||||
static const MASLayoutPriority MASLayoutPriorityDefaultHigh = UILayoutPriorityDefaultHigh;
|
||||
static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 500;
|
||||
static const MASLayoutPriority MASLayoutPriorityDefaultLow = UILayoutPriorityDefaultLow;
|
||||
static const MASLayoutPriority MASLayoutPriorityFittingSizeLevel = UILayoutPriorityFittingSizeLevel;
|
||||
|
||||
#elif TARGET_OS_MAC
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
#define MAS_VIEW NSView
|
||||
#define MASEdgeInsets NSEdgeInsets
|
||||
|
||||
typedef NSLayoutPriority MASLayoutPriority;
|
||||
static const MASLayoutPriority MASLayoutPriorityRequired = NSLayoutPriorityRequired;
|
||||
static const MASLayoutPriority MASLayoutPriorityDefaultHigh = NSLayoutPriorityDefaultHigh;
|
||||
static const MASLayoutPriority MASLayoutPriorityDragThatCanResizeWindow = NSLayoutPriorityDragThatCanResizeWindow;
|
||||
static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 501;
|
||||
static const MASLayoutPriority MASLayoutPriorityWindowSizeStayPut = NSLayoutPriorityWindowSizeStayPut;
|
||||
static const MASLayoutPriority MASLayoutPriorityDragThatCannotResizeWindow = NSLayoutPriorityDragThatCannotResizeWindow;
|
||||
static const MASLayoutPriority MASLayoutPriorityDefaultLow = NSLayoutPriorityDefaultLow;
|
||||
static const MASLayoutPriority MASLayoutPriorityFittingSizeCompression = NSLayoutPriorityFittingSizeCompression;
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Allows you to attach keys to objects matching the variable names passed.
|
||||
*
|
||||
* view1.mas_key = @"view1", view2.mas_key = @"view2";
|
||||
*
|
||||
* is equivalent to:
|
||||
*
|
||||
* MASAttachKeys(view1, view2);
|
||||
*/
|
||||
#define MASAttachKeys(...) \
|
||||
{ \
|
||||
NSDictionary *keyPairs = NSDictionaryOfVariableBindings(__VA_ARGS__); \
|
||||
for (id key in keyPairs.allKeys) { \
|
||||
id obj = keyPairs[key]; \
|
||||
NSAssert([obj respondsToSelector:@selector(setMas_key:)], \
|
||||
@"Cannot attach mas_key to %@", obj); \
|
||||
[obj setMas_key:key]; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to create object hashes
|
||||
* Based on http://www.mikeash.com/pyblog/friday-qa-2010-06-18-implementing-equality-and-hashing.html
|
||||
*/
|
||||
#define MAS_NSUINT_BIT (CHAR_BIT * sizeof(NSUInteger))
|
||||
#define MAS_NSUINTROTATE(val, howmuch) ((((NSUInteger)val) << howmuch) | (((NSUInteger)val) >> (MAS_NSUINT_BIT - howmuch)))
|
||||
|
||||
/**
|
||||
* Given a scalar or struct value, wraps it in NSValue
|
||||
* Based on EXPObjectify: https://github.com/specta/expecta
|
||||
*/
|
||||
static inline id _MASBoxValue(const char *type, ...) {
|
||||
va_list v;
|
||||
va_start(v, type);
|
||||
id obj = nil;
|
||||
if (strcmp(type, @encode(id)) == 0) {
|
||||
id actual = va_arg(v, id);
|
||||
obj = actual;
|
||||
} else if (strcmp(type, @encode(CGPoint)) == 0) {
|
||||
CGPoint actual = (CGPoint)va_arg(v, CGPoint);
|
||||
obj = [NSValue value:&actual withObjCType:type];
|
||||
} else if (strcmp(type, @encode(CGSize)) == 0) {
|
||||
CGSize actual = (CGSize)va_arg(v, CGSize);
|
||||
obj = [NSValue value:&actual withObjCType:type];
|
||||
} else if (strcmp(type, @encode(MASEdgeInsets)) == 0) {
|
||||
MASEdgeInsets actual = (MASEdgeInsets)va_arg(v, MASEdgeInsets);
|
||||
obj = [NSValue value:&actual withObjCType:type];
|
||||
} else if (strcmp(type, @encode(double)) == 0) {
|
||||
double actual = (double)va_arg(v, double);
|
||||
obj = [NSNumber numberWithDouble:actual];
|
||||
} else if (strcmp(type, @encode(float)) == 0) {
|
||||
float actual = (float)va_arg(v, double);
|
||||
obj = [NSNumber numberWithFloat:actual];
|
||||
} else if (strcmp(type, @encode(int)) == 0) {
|
||||
int actual = (int)va_arg(v, int);
|
||||
obj = [NSNumber numberWithInt:actual];
|
||||
} else if (strcmp(type, @encode(long)) == 0) {
|
||||
long actual = (long)va_arg(v, long);
|
||||
obj = [NSNumber numberWithLong:actual];
|
||||
} else if (strcmp(type, @encode(long long)) == 0) {
|
||||
long long actual = (long long)va_arg(v, long long);
|
||||
obj = [NSNumber numberWithLongLong:actual];
|
||||
} else if (strcmp(type, @encode(short)) == 0) {
|
||||
short actual = (short)va_arg(v, int);
|
||||
obj = [NSNumber numberWithShort:actual];
|
||||
} else if (strcmp(type, @encode(char)) == 0) {
|
||||
char actual = (char)va_arg(v, int);
|
||||
obj = [NSNumber numberWithChar:actual];
|
||||
} else if (strcmp(type, @encode(bool)) == 0) {
|
||||
bool actual = (bool)va_arg(v, int);
|
||||
obj = [NSNumber numberWithBool:actual];
|
||||
} else if (strcmp(type, @encode(unsigned char)) == 0) {
|
||||
unsigned char actual = (unsigned char)va_arg(v, unsigned int);
|
||||
obj = [NSNumber numberWithUnsignedChar:actual];
|
||||
} else if (strcmp(type, @encode(unsigned int)) == 0) {
|
||||
unsigned int actual = (unsigned int)va_arg(v, unsigned int);
|
||||
obj = [NSNumber numberWithUnsignedInt:actual];
|
||||
} else if (strcmp(type, @encode(unsigned long)) == 0) {
|
||||
unsigned long actual = (unsigned long)va_arg(v, unsigned long);
|
||||
obj = [NSNumber numberWithUnsignedLong:actual];
|
||||
} else if (strcmp(type, @encode(unsigned long long)) == 0) {
|
||||
unsigned long long actual = (unsigned long long)va_arg(v, unsigned long long);
|
||||
obj = [NSNumber numberWithUnsignedLongLong:actual];
|
||||
} else if (strcmp(type, @encode(unsigned short)) == 0) {
|
||||
unsigned short actual = (unsigned short)va_arg(v, unsigned int);
|
||||
obj = [NSNumber numberWithUnsignedShort:actual];
|
||||
}
|
||||
va_end(v);
|
||||
return obj;
|
||||
}
|
||||
|
||||
#define MASBoxValue(value) _MASBoxValue(@encode(__typeof__((value))), (value))
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user