上传ios工程资源包2

This commit is contained in:
2025-08-02 18:37:50 +08:00
parent 1e6e2b3c9a
commit 8cc0875b94
144 changed files with 12981 additions and 0 deletions
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