Cog/Utils/RedundantPlaylistDataStore.m
Christopher Snowhill e96a4efa68 [Metadata Loading] Added null pointer guards
This prevents crashes where inputs were not returning either properties
or metadata blocks and the file open cache was attempting to cache the
resulting nil pointer as if it were valid. Also prevent the metadata
redundant string coalescing from processing nil objects as well, in case
it's used that way somewhere else.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-09 23:18:51 -07:00

79 lines
1.8 KiB
Objective-C

//
// RedundantPlaylistDataStore.m
// Cog
//
// Created by Christopher Snowhill on 2/16/22.
//
// Coalesce an entryInfo dictionary from tag loading into a common data dictionary, to
// reduce the memory footprint of adding a lot of tracks to the playlist.
#import "RedundantPlaylistDataStore.h"
#import "SHA256Digest.h"
@implementation RedundantPlaylistDataStore
- (id)init {
self = [super init];
if(self) {
stringStore = [[NSMutableArray alloc] init];
artStore = [[NSMutableDictionary alloc] init];
}
return self;
}
- (NSString *)coalesceString:(NSString *)in {
if(in == nil) return in;
NSUInteger index = [stringStore indexOfObject:in];
if(index == NSNotFound) {
[stringStore addObject:in];
return in;
} else {
return [stringStore objectAtIndex:index];
}
}
- (NSData *)coalesceArt:(NSData *)in {
if(in == nil) return in;
NSString *key = [SHA256Digest digestDataAsString:in];
NSData *ret = [artStore objectForKey:key];
if(ret == nil) {
[artStore setObject:in forKey:key];
return in;
} else {
return ret;
}
}
- (NSDictionary *)coalesceEntryInfo:(NSDictionary *)entryInfo {
if(entryInfo == nil) return entryInfo;
__block NSMutableDictionary *ret = [[NSMutableDictionary alloc] initWithCapacity:[entryInfo count]];
[entryInfo enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL *_Nonnull stop) {
if([obj isKindOfClass:[NSString class]]) {
NSString *stringObj = (NSString *)obj;
[ret setObject:[self coalesceString:stringObj] forKey:key];
} else if([obj isKindOfClass:[NSData class]]) {
NSData *dataObj = (NSData *)obj;
[ret setObject:[self coalesceArt:dataObj] forKey:key];
} else {
[ret setObject:obj forKey:key];
}
}];
return [NSDictionary dictionaryWithDictionary:ret];
}
- (void)reset {
[stringStore removeAllObjects];
[artStore removeAllObjects];
}
@end