Files
flipper/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/ObjectMapper.m
Adam Cmiel a64d493875 - xplat sonar (#5091)
Summary:
Pull Request resolved: https://github.com/facebook/flipper/pull/5091

https://developer.apple.com/documentation/foundation/nsstring/1497289-stringwithcstring

[Changelog]:[Fixed] Remove usage of deprecated stringWithCString function

Reviewed By: lblasa

Differential Revision: D48692608

fbshipit-source-id: 683d6f8656fe6183cb02faab6261f1b6a61cc3a2
2023-09-06 13:09:09 -07:00

217 lines
7.3 KiB
Objective-C

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "ObjectMapper.h"
#include <Foundation/Foundation.h>
#import "DatabaseDescriptorHolder.h"
#import "DatabaseExecuteSql.h"
#import "DatabaseGetTableData.h"
#import "DatabaseGetTableInfo.h"
#import "DatabaseGetTableStructure.h"
@implementation ObjectMapper
static const int MAX_BLOB_LENGTH = 100 * 1024;
static NSString* const UNKNOWN_BLOB_LABEL_FORMAT = @"{%d-byte %@ blob}";
+ (NSMutableArray*)databaseListToFlipperArray:
(NSMutableSet<DatabaseDescriptorHolder*>*)databaseDescriptorHolderSet {
NSMutableArray* result = [NSMutableArray new];
for (DatabaseDescriptorHolder* holder in databaseDescriptorHolderSet) {
NSArray<NSString*>* tables =
[holder.databaseDriver getTableNames:holder.databaseDescriptor];
NSArray<NSString*>* sortedTableNames =
[tables sortedArrayUsingSelector:@selector(compare:)];
NSString* idString = [NSString stringWithFormat:@"%ld", holder.identifier];
NSDictionary* databaseInfo = @{
@"id" : idString,
@"name" : holder.databaseDescriptor.name,
@"tables" : sortedTableNames
};
[result addObject:databaseInfo];
}
return result;
}
+ (NSDictionary*)databaseGetTableDataResponseToDictionary:
(DatabaseGetTableDataResponse*)response {
NSMutableArray* rows = [NSMutableArray array];
for (NSArray* row in response.values) {
NSMutableArray* rowValues = [NSMutableArray array];
for (id item in row) {
[rowValues addObject:[self objectAndTypeToFlipperObject:item]];
}
[rows addObject:rowValues];
}
return @{
@"columns" : response.columns,
@"values" : rows,
@"start" : @(response.start),
@"count" : @(response.count),
@"total" : @(response.total)
};
}
+ (NSDictionary*)errorWithCode:(NSInteger)code message:(NSString*)message {
return @{@"code" : @(code), @"message" : message};
}
+ (NSDictionary*)databaseGetTableStructureResponseToDictionary:
(DatabaseGetTableStructureResponse*)response {
NSMutableArray* structureValues = [NSMutableArray array];
for (NSArray* row in response.structureValues) {
NSMutableArray* rowValues = [NSMutableArray array];
for (id item in row) {
[rowValues addObject:[self objectAndTypeToFlipperObject:item]];
}
[structureValues addObject:rowValues];
}
NSMutableArray* indexesValues = [NSMutableArray array];
for (NSArray* row in response.indexesValues) {
NSMutableArray* rowValues = [NSMutableArray array];
for (id item in row) {
[rowValues addObject:[self objectAndTypeToFlipperObject:item]];
}
[indexesValues addObject:rowValues];
}
return @{
@"structureColumns" : response.structureColumns,
@"structureValues" : structureValues,
@"indexesColumns" : response.indexesColumns,
@"indexesValues" : indexesValues
};
}
+ (NSDictionary*)databaseGetTableInfoResponseToDictionary:
(DatabaseGetTableInfoResponse*)response {
return @{
@"definition" : response.definition,
};
}
+ (NSDictionary*)databaseExecuteSqlResponseToDictionary:
(DatabaseExecuteSqlResponse*)response {
NSMutableArray* rows = [NSMutableArray array];
if (response.values) {
for (NSArray* row in response.values) {
NSMutableArray* rowValues = [NSMutableArray array];
for (id item in row) {
[rowValues addObject:[self objectAndTypeToFlipperObject:item]];
}
[rows addObject:rowValues];
}
}
NSMutableDictionary* result = [NSMutableDictionary dictionaryWithDictionary:@{
@"type" : response.type,
@"columns" : response.columns,
@"values" : rows,
@"affectedCount" : @(response.affectedCount)
}];
if (response.insertedId) {
result[@"insertedId"] = response.insertedId;
}
return result;
}
+ (NSDictionary*)objectAndTypeToFlipperObject:(id)object {
if (!object || [object isKindOfClass:[NSNull class]]) {
return @{@"type" : @"null"};
} else if ([object isKindOfClass:[NSNumber class]]) {
NSNumber* number = (NSNumber*)object;
NSString* type = [NSString stringWithUTF8String:[number objCType]];
if ([type isEqualToString:@"i"]) {
return @{@"type" : @"integer", @"value" : number};
} else if ([type isEqualToString:@"f"] || [type isEqualToString:@"d"]) {
return @{@"type" : @"float", @"value" : number};
} else if ([type isEqualToString:@"B"]) {
return @{@"type" : @"boolean", @"value" : number};
} else {
return @{@"type" : @"integer", @"value" : @([number integerValue])};
}
return @{@"type" : @"integer", @"value" : object};
} else if ([object isKindOfClass:[NSDecimalNumber class]]) {
return @{@"type" : @"float", @"value" : object};
} else if ([object isKindOfClass:[NSString class]]) {
return @{@"type" : @"string", @"value" : object};
} else if ([object isKindOfClass:[NSData class]]) {
NSString* blobString = [self blobToString:(NSData*)object];
return @{@"type" : @"blob", @"value" : blobString};
} else if ([object isKindOfClass:[NSDictionary class]]) {
// Usualy the dictionary is a Json blob, and we can parse it as string.
NSError* error;
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:object
options:0
error:&error];
if (!jsonData) {
NSString* reason = [NSString
stringWithFormat:@"NSDictionary is not in a json format: %@",
[error localizedDescription]];
@throw [NSException exceptionWithName:@"InvalidArgumentException"
reason:reason
userInfo:nil];
}
NSString* jsonString = [[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding];
return @{@"type" : @"blob", @"value" : jsonString};
} else if ([object isKindOfClass:[NSValue class]]) {
return @{@"type" : @"boolean", @"value" : object};
} else {
@throw [NSException exceptionWithName:@"InvalidArgumentException"
reason:@"type of Object is invalid"
userInfo:nil];
}
}
+ (NSString*)blobToString:(NSData*)data {
const uint8_t* bytes = data.bytes;
uint length = data.length;
if (length <= MAX_BLOB_LENGTH) {
if ([self fastIsAscii:bytes length:length]) {
NSStringEncoding encoding = NSASCIIStringEncoding;
return [[NSString alloc] initWithBytesNoCopy:(void*)bytes
length:length
encoding:encoding
freeWhenDone:NO];
} else {
// try UTF-8
NSStringEncoding encoding = NSUTF8StringEncoding;
return [[NSString alloc] initWithBytesNoCopy:(void*)bytes
length:length
encoding:encoding
freeWhenDone:NO];
}
}
return
[NSString stringWithFormat:UNKNOWN_BLOB_LABEL_FORMAT, length, @"binary"];
}
+ (BOOL)fastIsAscii:(const uint8_t*)bytes length:(NSUInteger)length {
for (int i = 0; i < length; i++) {
uint8_t b = bytes[i];
if ((b & ~0x7f) != 0) {
return NO;
}
}
return YES;
}
@end