From 83b9d5c682b21d88133f24da0f94dd56bd79e687 Mon Sep 17 00:00:00 2001 From: 单军华 Date: Thu, 19 Jul 2018 13:38:55 +0800 Subject: [PATCH] change --- screendisplay/Pods/YYCache/YYCache/YYDiskCache.m | 458 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 458 insertions(+), 0 deletions(-) diff --git a/screendisplay/Pods/YYCache/YYCache/YYDiskCache.m b/screendisplay/Pods/YYCache/YYCache/YYDiskCache.m new file mode 100644 index 0000000..735cc5d --- /dev/null +++ b/screendisplay/Pods/YYCache/YYCache/YYDiskCache.m @@ -0,0 +1,458 @@ +// +// YYDiskCache.m +// YYCache <https://github.com/ibireme/YYCache> +// +// Created by ibireme on 15/2/11. +// Copyright (c) 2015 ibireme. +// +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. +// + +#import "YYDiskCache.h" +#import "YYKVStorage.h" +#import <UIKit/UIKit.h> +#import <CommonCrypto/CommonCrypto.h> +#import <objc/runtime.h> +#import <time.h> + +#define Lock() dispatch_semaphore_wait(self->_lock, DISPATCH_TIME_FOREVER) +#define Unlock() dispatch_semaphore_signal(self->_lock) + +static const int extended_data_key; + +/// Free disk space in bytes. +static int64_t _YYDiskSpaceFree() { + NSError *error = nil; + NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error]; + if (error) return -1; + int64_t space = [[attrs objectForKey:NSFileSystemFreeSize] longLongValue]; + if (space < 0) space = -1; + return space; +} + +/// String's md5 hash. +static NSString *_YYNSStringMD5(NSString *string) { + if (!string) return nil; + NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; + unsigned char result[CC_MD5_DIGEST_LENGTH]; + CC_MD5(data.bytes, (CC_LONG)data.length, result); + return [NSString stringWithFormat: + @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + result[0], result[1], result[2], result[3], + result[4], result[5], result[6], result[7], + result[8], result[9], result[10], result[11], + result[12], result[13], result[14], result[15] + ]; +} + +/// weak reference for all instances +static NSMapTable *_globalInstances; +static dispatch_semaphore_t _globalInstancesLock; + +static void _YYDiskCacheInitGlobal() { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _globalInstancesLock = dispatch_semaphore_create(1); + _globalInstances = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:0]; + }); +} + +static YYDiskCache *_YYDiskCacheGetGlobal(NSString *path) { + if (path.length == 0) return nil; + _YYDiskCacheInitGlobal(); + dispatch_semaphore_wait(_globalInstancesLock, DISPATCH_TIME_FOREVER); + id cache = [_globalInstances objectForKey:path]; + dispatch_semaphore_signal(_globalInstancesLock); + return cache; +} + +static void _YYDiskCacheSetGlobal(YYDiskCache *cache) { + if (cache.path.length == 0) return; + _YYDiskCacheInitGlobal(); + dispatch_semaphore_wait(_globalInstancesLock, DISPATCH_TIME_FOREVER); + [_globalInstances setObject:cache forKey:cache.path]; + dispatch_semaphore_signal(_globalInstancesLock); +} + + + +@implementation YYDiskCache { + YYKVStorage *_kv; + dispatch_semaphore_t _lock; + dispatch_queue_t _queue; +} + +- (void)_trimRecursively { + __weak typeof(self) _self = self; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_autoTrimInterval * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ + __strong typeof(_self) self = _self; + if (!self) return; + [self _trimInBackground]; + [self _trimRecursively]; + }); +} + +- (void)_trimInBackground { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + if (!self) return; + Lock(); + [self _trimToCost:self.costLimit]; + [self _trimToCount:self.countLimit]; + [self _trimToAge:self.ageLimit]; + [self _trimToFreeDiskSpace:self.freeDiskSpaceLimit]; + Unlock(); + }); +} + +- (void)_trimToCost:(NSUInteger)costLimit { + if (costLimit >= INT_MAX) return; + [_kv removeItemsToFitSize:(int)costLimit]; + +} + +- (void)_trimToCount:(NSUInteger)countLimit { + if (countLimit >= INT_MAX) return; + [_kv removeItemsToFitCount:(int)countLimit]; +} + +- (void)_trimToAge:(NSTimeInterval)ageLimit { + if (ageLimit <= 0) { + [_kv removeAllItems]; + return; + } + long timestamp = time(NULL); + if (timestamp <= ageLimit) return; + long age = timestamp - ageLimit; + if (age >= INT_MAX) return; + [_kv removeItemsEarlierThanTime:(int)age]; +} + +- (void)_trimToFreeDiskSpace:(NSUInteger)targetFreeDiskSpace { + if (targetFreeDiskSpace == 0) return; + int64_t totalBytes = [_kv getItemsSize]; + if (totalBytes <= 0) return; + int64_t diskFreeBytes = _YYDiskSpaceFree(); + if (diskFreeBytes < 0) return; + int64_t needTrimBytes = targetFreeDiskSpace - diskFreeBytes; + if (needTrimBytes <= 0) return; + int64_t costLimit = totalBytes - needTrimBytes; + if (costLimit < 0) costLimit = 0; + [self _trimToCost:(int)costLimit]; +} + +- (NSString *)_filenameForKey:(NSString *)key { + NSString *filename = nil; + if (_customFileNameBlock) filename = _customFileNameBlock(key); + if (!filename) filename = _YYNSStringMD5(key); + return filename; +} + +- (void)_appWillBeTerminated { + Lock(); + _kv = nil; + Unlock(); +} + +#pragma mark - public + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil]; +} + +- (instancetype)init { + @throw [NSException exceptionWithName:@"YYDiskCache init error" reason:@"YYDiskCache must be initialized with a path. Use 'initWithPath:' or 'initWithPath:inlineThreshold:' instead." userInfo:nil]; + return [self initWithPath:@"" inlineThreshold:0]; +} + +- (instancetype)initWithPath:(NSString *)path { + return [self initWithPath:path inlineThreshold:1024 * 20]; // 20KB +} + +- (instancetype)initWithPath:(NSString *)path + inlineThreshold:(NSUInteger)threshold { + self = [super init]; + if (!self) return nil; + + YYDiskCache *globalCache = _YYDiskCacheGetGlobal(path); + if (globalCache) return globalCache; + + YYKVStorageType type; + if (threshold == 0) { + type = YYKVStorageTypeFile; + } else if (threshold == NSUIntegerMax) { + type = YYKVStorageTypeSQLite; + } else { + type = YYKVStorageTypeMixed; + } + + YYKVStorage *kv = [[YYKVStorage alloc] initWithPath:path type:type]; + if (!kv) return nil; + + _kv = kv; + _path = path; + _lock = dispatch_semaphore_create(1); + _queue = dispatch_queue_create("com.ibireme.cache.disk", DISPATCH_QUEUE_CONCURRENT); + _inlineThreshold = threshold; + _countLimit = NSUIntegerMax; + _costLimit = NSUIntegerMax; + _ageLimit = DBL_MAX; + _freeDiskSpaceLimit = 0; + _autoTrimInterval = 60; + + [self _trimRecursively]; + _YYDiskCacheSetGlobal(self); + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appWillBeTerminated) name:UIApplicationWillTerminateNotification object:nil]; + return self; +} + +- (BOOL)containsObjectForKey:(NSString *)key { + if (!key) return NO; + Lock(); + BOOL contains = [_kv itemExistsForKey:key]; + Unlock(); + return contains; +} + +- (void)containsObjectForKey:(NSString *)key withBlock:(void(^)(NSString *key, BOOL contains))block { + if (!block) return; + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + BOOL contains = [self containsObjectForKey:key]; + block(key, contains); + }); +} + +- (id<NSCoding>)objectForKey:(NSString *)key { + if (!key) return nil; + Lock(); + YYKVStorageItem *item = [_kv getItemForKey:key]; + Unlock(); + if (!item.value) return nil; + + id object = nil; + if (_customUnarchiveBlock) { + object = _customUnarchiveBlock(item.value); + } else { + @try { + object = [NSKeyedUnarchiver unarchiveObjectWithData:item.value]; + } + @catch (NSException *exception) { + // nothing to do... + } + } + if (object && item.extendedData) { + [YYDiskCache setExtendedData:item.extendedData toObject:object]; + } + return object; +} + +- (void)objectForKey:(NSString *)key withBlock:(void(^)(NSString *key, id<NSCoding> object))block { + if (!block) return; + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + id<NSCoding> object = [self objectForKey:key]; + block(key, object); + }); +} + +- (void)setObject:(id<NSCoding>)object forKey:(NSString *)key { + if (!key) return; + if (!object) { + [self removeObjectForKey:key]; + return; + } + + NSData *extendedData = [YYDiskCache getExtendedDataFromObject:object]; + NSData *value = nil; + if (_customArchiveBlock) { + value = _customArchiveBlock(object); + } else { + @try { + value = [NSKeyedArchiver archivedDataWithRootObject:object]; + } + @catch (NSException *exception) { + // nothing to do... + } + } + if (!value) return; + NSString *filename = nil; + if (_kv.type != YYKVStorageTypeSQLite) { + if (value.length > _inlineThreshold) { + filename = [self _filenameForKey:key]; + } + } + + Lock(); + [_kv saveItemWithKey:key value:value filename:filename extendedData:extendedData]; + Unlock(); +} + +- (void)setObject:(id<NSCoding>)object forKey:(NSString *)key withBlock:(void(^)(void))block { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + [self setObject:object forKey:key]; + if (block) block(); + }); +} + +- (void)removeObjectForKey:(NSString *)key { + if (!key) return; + Lock(); + [_kv removeItemForKey:key]; + Unlock(); +} + +- (void)removeObjectForKey:(NSString *)key withBlock:(void(^)(NSString *key))block { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + [self removeObjectForKey:key]; + if (block) block(key); + }); +} + +- (void)removeAllObjects { + Lock(); + [_kv removeAllItems]; + Unlock(); +} + +- (void)removeAllObjectsWithBlock:(void(^)(void))block { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + [self removeAllObjects]; + if (block) block(); + }); +} + +- (void)removeAllObjectsWithProgressBlock:(void(^)(int removedCount, int totalCount))progress + endBlock:(void(^)(BOOL error))end { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + if (!self) { + if (end) end(YES); + return; + } + Lock(); + [_kv removeAllItemsWithProgressBlock:progress endBlock:end]; + Unlock(); + }); +} + +- (NSInteger)totalCount { + Lock(); + int count = [_kv getItemsCount]; + Unlock(); + return count; +} + +- (void)totalCountWithBlock:(void(^)(NSInteger totalCount))block { + if (!block) return; + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + NSInteger totalCount = [self totalCount]; + block(totalCount); + }); +} + +- (NSInteger)totalCost { + Lock(); + int count = [_kv getItemsSize]; + Unlock(); + return count; +} + +- (void)totalCostWithBlock:(void(^)(NSInteger totalCost))block { + if (!block) return; + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + NSInteger totalCost = [self totalCost]; + block(totalCost); + }); +} + +- (void)trimToCount:(NSUInteger)count { + Lock(); + [self _trimToCount:count]; + Unlock(); +} + +- (void)trimToCount:(NSUInteger)count withBlock:(void(^)(void))block { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + [self trimToCount:count]; + if (block) block(); + }); +} + +- (void)trimToCost:(NSUInteger)cost { + Lock(); + [self _trimToCost:cost]; + Unlock(); +} + +- (void)trimToCost:(NSUInteger)cost withBlock:(void(^)(void))block { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + [self trimToCost:cost]; + if (block) block(); + }); +} + +- (void)trimToAge:(NSTimeInterval)age { + Lock(); + [self _trimToAge:age]; + Unlock(); +} + +- (void)trimToAge:(NSTimeInterval)age withBlock:(void(^)(void))block { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + [self trimToAge:age]; + if (block) block(); + }); +} + ++ (NSData *)getExtendedDataFromObject:(id)object { + if (!object) return nil; + return (NSData *)objc_getAssociatedObject(object, &extended_data_key); +} + ++ (void)setExtendedData:(NSData *)extendedData toObject:(id)object { + if (!object) return; + objc_setAssociatedObject(object, &extended_data_key, extendedData, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (NSString *)description { + if (_name) return [NSString stringWithFormat:@"<%@: %p> (%@:%@)", self.class, self, _name, _path]; + else return [NSString stringWithFormat:@"<%@: %p> (%@)", self.class, self, _path]; +} + +- (BOOL)errorLogsEnabled { + Lock(); + BOOL enabled = _kv.errorLogsEnabled; + Unlock(); + return enabled; +} + +- (void)setErrorLogsEnabled:(BOOL)errorLogsEnabled { + Lock(); + _kv.errorLogsEnabled = errorLogsEnabled; + Unlock(); +} + +@end -- Gitblit v1.8.0