#include "jni.h" #include #include #include #include #include "log.h" #include "utils.h" CFTypeRef SecTaskCopyValueForEntitlement(void* task, NSString* entitlement, CFErrorRef _Nullable *error); void* SecTaskCreateFromSelf(CFAllocatorRef allocator); BOOL getEntitlementValue(NSString *key) { void *secTask = SecTaskCreateFromSelf(NULL); CFTypeRef value = SecTaskCopyValueForEntitlement(SecTaskCreateFromSelf(NULL), key, nil); if (value != nil) { CFRelease(value); } CFRelease(secTask); return value != nil && [(__bridge id)value boolValue]; } BOOL isJITEnabled() { if (getEntitlementValue(@"dynamic-codesigning")) { return YES; } int flags; csops(getpid(), 0, &flags, sizeof(flags)); return (flags & CS_DEBUGGED) != 0; } NSMutableDictionary* parseJSONFromFile(NSString *path) { NSError *error; NSString *content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error]; if (content == nil) { NSLog(@"[ParseJSON] Error: could not read %@: %@", path, error.localizedDescription); return [@{@"error": error} mutableCopy]; } NSData* data = [content dataUsingEncoding:NSUTF8StringEncoding]; NSMutableDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error]; if (error) { NSLog(@"[ParseJSON] Error: could not parse JSON: %@", error.localizedDescription); return [@{@"error": error} mutableCopy]; } return dict; } NSError* saveJSONToFile(NSDictionary *dict, NSString *path) { // TODO: handle rename NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&error]; if (jsonData == nil) { return error; } BOOL success = [jsonData writeToFile:path options:NSDataWritingAtomic error:&error]; if (!success) { return error; } return nil; } NSString* localize(NSString* key, NSString* comment) { NSString *value = NSLocalizedString(key, nil); if (![NSLocale.preferredLanguages[0] isEqualToString:@"en"] && [value isEqualToString:key]) { NSString* path = [NSBundle.mainBundle pathForResource:@"en" ofType:@"lproj"]; NSBundle* languageBundle = [NSBundle bundleWithPath:path]; value = [languageBundle localizedStringForKey:key value:nil table:nil]; if ([value isEqualToString:key]) { value = [[NSBundle bundleWithIdentifier:@"com.apple.UIKit"] localizedStringForKey:key value:nil table:nil]; } } return value; } CGFloat MathUtils_dist(CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2) { const CGFloat x = (x2 - x1); const CGFloat y = (y2 - y1); return (CGFloat) hypot(x, y); } //Ported from https://www.arduino.cc/reference/en/language/functions/math/map/ CGFloat MathUtils_map(CGFloat x, CGFloat in_min, CGFloat in_max, CGFloat out_min, CGFloat out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } void _CGDataProviderReleaseBytePointerCallback(void *info,const void *pointer) { } CGFloat dpToPx(CGFloat dp) { CGFloat screenScale = [[UIScreen mainScreen] scale]; return dp * screenScale; } CGFloat pxToDp(CGFloat px) { CGFloat screenScale = [[UIScreen mainScreen] scale]; return px / screenScale; } void setButtonPointerInteraction(UIButton *button) { if(@available (iOS 13.4, *)) { button.pointerInteractionEnabled = YES; button.pointerStyleProvider = ^ UIPointerStyle* (UIButton* button, UIPointerEffect* proposedEffect, UIPointerShape* proposedShape) { UITargetedPreview *preview = [[UITargetedPreview alloc] initWithView:button]; return [UIPointerStyle styleWithEffect:[UIPointerHighlightEffect effectWithPreview:preview] shape:proposedShape]; }; } } void setViewBackgroundColor(UIView* view) { if(@available(iOS 13.0, *)) { view.backgroundColor = UIColor.systemBackgroundColor; } else { view.backgroundColor = UIColor.whiteColor; } }