123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- //
- // XSDataCenter.m
- // XenonSDK
- //
- // Created by SAGESSE on 2019/5/30.
- // Copyright © 2019 SAGESSE. All rights reserved.
- //
- #import "XenonSDK.h"
- #import "XSDataCenter.h"
- #if SDK_USE_DATA_DB
- #import <sqlite3.h>
- #endif
- @implementation XSDataCenter
- + (NSString*)path {
- return [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSAllDomainsMask, YES) firstObject];
- }
- #if SDK_USE_DATA_DB
- + (sqlite3*)db {
- static sqlite3* db = nil;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- // Check file path.
- if (![NSFileManager.defaultManager fileExistsAtPath:self.path]) {
- [NSFileManager.defaultManager createDirectoryAtPath:self.path withIntermediateDirectories:YES attributes:nil error:nil];
- }
- NSString* path = [self.path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.db", NSStringFromClass(self)]];
- if (sqlite3_open(path.UTF8String, &db) != 0) {
- db = nil;
- return;
- }
- if (sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS 'DC' ('key' TEXT NOT NULL PRIMARY KEY, 'value' TEXT, 'isa' TEXT);", nil, nil, nil) != 0) {
- db = nil;
- return;
- }
- });
- return db;
- }
- #endif
- + (void)setString:(id)value forKey:(id)key {
- [self setValue:[NSArray arrayWithObject:value]
- forKey:key];
- }
- + (id)stringForKey:(id)key {
- return [[self valueForKey:key] firstObject];
- }
- + (void)setDouble:(CGFloat)value forKey:(id)key {
- [self setValue:@[@(value)]
- forKey:key];
- }
- + (CGFloat)doubleForKey:(id)key {
- return [[[self valueForKey:key] firstObject] doubleValue];
- }
- + (void)setValue:(id)value forKey:(id)key {
- // Must be locked.
- @synchronized (self) {
- // To data;
- id isa = NSStringFromClass([value class]);
- id json = value;
- if ([json isKindOfClass:NSArray.class]) {
- __block id nisa = nil;
- NSMutableArray* res = [NSMutableArray array];
- [json enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
- if ([obj isKindOfClass:JSONModel.class]) {
- nisa = NSStringFromClass([obj class]);
- [res addObject:[obj toDictionary]];
- } else {
- nisa = nil;
- *stop = YES;
- }
- }];
- // Same type.
- if (nisa != nil) {
- json = res;
- isa = nisa;
- }
- }
- if ([json isKindOfClass:JSONModel.class]) {
- json = [value toDictionary];
- }
- if (json != nil) {
- id data = [NSJSONSerialization dataWithJSONObject:json options:0 error:nil];
- json = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; ;
- }
-
- #if SDK_USE_DATA_DB
- NSString* dw = sdk_md5(key);
- NSString* dsql = [NSString stringWithFormat:@"DELETE FROM DC WHERE key = '%@';", dw];
- sqlite3_exec(self.db, dsql.UTF8String, nil, nil, nil);
- if (json != nil) {
- NSString* base64 = [[json dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];
- NSString* isql = [NSString stringWithFormat:@"INSERT INTO DC (key, value, isa) VALUES ('%@', '%@', '%@');", dw, base64, isa];
- sqlite3_exec(self.db, isql.UTF8String, nil, nil, nil);
- }
- #endif
- #if SDK_USE_DATA_UD
- if (value == nil) {
- [NSUserDefaults.standardUserDefaults setObject:nil forKey:key];
- [NSUserDefaults.standardUserDefaults synchronize];
- } else {
- [NSUserDefaults.standardUserDefaults setObject:@[isa, json] forKey:key];
- [NSUserDefaults.standardUserDefaults synchronize];
- }
- #endif
- #if SDK_USE_DATA_FILE
- // Check file path.
- if (![NSFileManager.defaultManager fileExistsAtPath:self.path]) {
- [NSFileManager.defaultManager createDirectoryAtPath:self.path withIntermediateDirectories:YES attributes:nil error:nil];
- }
-
- // Make new path.
- NSString* path = [self.path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.db", sdk_md5(key)]];
-
- if (value == nil) {
- [NSFileManager.defaultManager removeItemAtPath:path error:nil];
- } else {
- [@[isa, json] writeToFile:path atomically:YES];
- }
- #endif
- }
- }
- + (id)valueForKey:(id)key {
- // Must be locked.
- @synchronized (self) {
-
- NSString* isa = nil;
- NSString* json = nil;
-
- #if SDK_USE_DATA_DB
- NSString* dw = sdk_md5(key);
- NSString* qsql = [NSString stringWithFormat:@"SELECT isa, value FROM DC WHERE key = '%@';", dw];
- sqlite3_stmt* stmt = nil;
- if (sqlite3_prepare_v2(self.db, qsql.UTF8String, -1, &stmt, nil) != 0) {
- return nil;
- }
-
- sqlite3_step(stmt);
- void* col1 = (void*)sqlite3_column_text(stmt, 0);
- void* col2 = (void*)sqlite3_column_text(stmt, 1);
-
- if (col1 != nil) {
- isa = [NSString stringWithUTF8String:col1];
- }
- if (col2 != nil) {
- NSData* data = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:col2] options:0];
- json = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- }
- sqlite3_finalize(stmt);
- #endif
- #if SDK_USE_DATA_UD
- NSArray* uaw = [NSUserDefaults.standardUserDefaults arrayForKey:key];
- if (uaw.count == 2) {
- isa = uaw[0];
- json = uaw[1];
- }
- #endif
- #if SDK_USE_DATA_FILE
- // Make new path.
- NSString* path = [self.path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.db", sdk_md5(key)]];
- NSArray* faw = [NSArray arrayWithContentsOfFile:path];
- if (faw.count == 2) {
- isa = faw[0];
- json = faw[1];
- }
- #endif
-
- if (isa != nil || json != nil) {
- Class cls = NSClassFromString(isa);
- NSData* data = [json dataUsingEncoding:NSUTF8StringEncoding];
- id object = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
- if ([cls isSubclassOfClass:JSONModel.class]) {
- if ([object isKindOfClass:NSArray.class]) {
- return [cls arrayOfModelsFromDictionaries:object error:nil];
- }
- return [[cls alloc] initWithDictionary:object error:nil];
- }
- return object;
- }
-
- return nil;
- }
- }
- //class func set<T: Encodable>(_ value: T?, forKey key: String) {
- //
- //}
- //
- //class func value<T: Decodable>(forKey key: String) -> T? {
- // // Must be locked.
- // objc_sync_enter(self)
- // defer {
- // objc_sync_exit(self)
- // }
- //
- // var value: T?
- //
- //#if SDK_USE_DATA_DB
- // var stmt: UnsafeRawPointer?
- // guard sqlite3_prepare_v2(db, "SELECT value FROM DC WHERE key = '\(sdk_md5(key))';", -1, &stmt, nil) == 0 else {
- // return nil
- // }
- // defer {
- // _ = sqlite3_finalize(stmt)
- // }
- // _ = sqlite3_step(stmt)
- // guard let ptr = sqlite3_column_text(stmt, 0), let str = NSString(cString: ptr, encoding: String.Encoding.utf8.rawValue) else {
- // return nil
- // }
- // let data = Data(base64Encoded: str as String)
- // let decoder = PropertyListDecoder()
- // value = try? data.map { try decoder.decode(T.self, from: $0) }
- //#endif
- //
- //#if SDK_USE_DATA_UD
- // let data = UserDefaults.standard.data(forKey: defaultName)
- // let decoder = PropertyListDecoder()
- // value = try? data.map { try decoder.decode(T.self, from: $0) }
- //#endif
- //
- //#if SDK_USE_DATA_FILE
- // guard let path = XSDataCenter.path else {
- // return nil
- // }
- // var url = URL(fileURLWithPath: path)
- // url.appendPathComponent("\(sdk_md5(key)).db")
- // let data = try? Data(contentsOf: url)
- // let decoder = PropertyListDecoder()
- // value = try? data.map { try decoder.decode(T.self, from: $0) }
- //#endif
- //
- // return value
- //}
- @end
|