From cae85b7401466baf6acc8f790ae690b126eb92f5 Mon Sep 17 00:00:00 2001 From: meancoot Date: Wed, 20 Feb 2013 23:30:56 -0500 Subject: [PATCH] ios: Have the list_directory use objects to cache properties about the items. Quite a bit faster too. --- ios/RetroArch/RADirectoryGrid.m | 15 +++---- ios/RetroArch/RADirectoryList.m | 17 ++++---- ios/RetroArch/browser.h | 5 +++ ios/RetroArch/browser.m | 77 +++++++++++++++++++++++++-------- 4 files changed, 78 insertions(+), 36 deletions(-) diff --git a/ios/RetroArch/RADirectoryGrid.m b/ios/RetroArch/RADirectoryGrid.m index 1bd0403d3d..6a6a7cca74 100644 --- a/ios/RetroArch/RADirectoryGrid.m +++ b/ios/RetroArch/RADirectoryGrid.m @@ -58,25 +58,24 @@ - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { - NSString* path = [_list objectAtIndex: indexPath.row]; + RADirectoryItem* path = [_list objectAtIndex: indexPath.row]; - if(ra_ios_is_directory(path)) - [[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListWithPath:path]]; + if(path.isDirectory) + [[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListWithPath:path.path]]; else - [[RetroArch_iOS get] runGame:path]; + [[RetroArch_iOS get] runGame:path.path]; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { - NSString* path = [_list objectAtIndex: indexPath.row]; - BOOL isdir = ra_ios_is_directory(path); + RADirectoryItem* path = [_list objectAtIndex: indexPath.row]; UICollectionViewCell* cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"filecell" forIndexPath:indexPath]; - if (isdir) + if (path.isDirectory) cell.backgroundView = [[UIImageView alloc] initWithImage:[RetroArch_iOS get].folder_icon]; else { - NSString* img = [NSString stringWithFormat:@"%@/.coverart/%@.png", _path, [[path lastPathComponent] stringByDeletingPathExtension]]; + NSString* img = [NSString stringWithFormat:@"%@/.coverart/%@.png", _path, [[path.path lastPathComponent] stringByDeletingPathExtension]]; if (ra_ios_is_file(img)) cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:img]]; else diff --git a/ios/RetroArch/RADirectoryList.m b/ios/RetroArch/RADirectoryList.m index a25cb9c2d3..adda1f5150 100644 --- a/ios/RetroArch/RADirectoryList.m +++ b/ios/RetroArch/RADirectoryList.m @@ -71,12 +71,12 @@ static NSString* check_path(NSString* path) - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - NSString* path = [_list objectAtIndex: indexPath.row]; + RADirectoryItem* path = [_list objectAtIndex: indexPath.row]; - if(ra_ios_is_directory(path)) - [[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListWithPath:path]]; + if(path.isDirectory) + [[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListWithPath:path.path]]; else - [[RetroArch_iOS get] runGame:path]; + [[RetroArch_iOS get] runGame:path.path]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section @@ -86,14 +86,13 @@ static NSString* check_path(NSString* path) - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - NSString* path = [_list objectAtIndex: indexPath.row]; - BOOL isdir = ra_ios_is_directory(path); + RADirectoryItem* path = [_list objectAtIndex: indexPath.row]; UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"path"]; cell = (cell != nil) ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"path"]; - cell.textLabel.text = [path lastPathComponent]; - cell.accessoryType = (isdir) ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone; - cell.imageView.image = (isdir) ? [RetroArch_iOS get].folder_icon : [RetroArch_iOS get].file_icon; + cell.textLabel.text = [path.path lastPathComponent]; + cell.accessoryType = (path.isDirectory) ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone; + cell.imageView.image = (path.isDirectory) ? [RetroArch_iOS get].folder_icon : [RetroArch_iOS get].file_icon; return cell; } diff --git a/ios/RetroArch/browser.h b/ios/RetroArch/browser.h index ea7b7b74d3..ce66c4c412 100644 --- a/ios/RetroArch/browser.h +++ b/ios/RetroArch/browser.h @@ -18,6 +18,11 @@ extern BOOL ra_ios_is_file(NSString* path); extern NSArray* ra_ios_list_directory(NSString* path, NSRegularExpression* regex); extern NSString* ra_ios_get_browser_root(); +@interface RADirectoryItem : NSObject +@property (strong) NSString* path; +@property bool isDirectory; +@end + @interface RADirectoryGrid : UICollectionViewController - (id)initWithPath:(NSString*)path filter:(NSRegularExpression*)regex; @end diff --git a/ios/RetroArch/browser.m b/ios/RetroArch/browser.m index 7785ec952d..3b39e1c4d0 100644 --- a/ios/RetroArch/browser.m +++ b/ios/RetroArch/browser.m @@ -13,6 +13,25 @@ * If not, see . */ +#include +#include +#import "browser.h" + +@implementation RADirectoryItem ++ (RADirectoryItem*)directoryItemFromPath:(const char*)thePath +{ + RADirectoryItem* result = [RADirectoryItem new]; + result.path = [NSString stringWithUTF8String:thePath]; + + struct stat statbuf; + if (stat(thePath, &statbuf) == 0) + result.isDirectory = S_ISDIR(statbuf.st_mode); + + return result; +} +@end + + BOOL ra_ios_is_file(NSString* path) { return [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:nil]; @@ -27,30 +46,50 @@ BOOL ra_ios_is_directory(NSString* path) NSArray* ra_ios_list_directory(NSString* path, NSRegularExpression* regex) { - NSArray* result = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil]; - result = [path stringsByAppendingPaths:result]; + NSMutableArray* result = [NSMutableArray array]; + + // Build list + char* cpath = malloc([path length] + sizeof(struct dirent)); + sprintf(cpath, "%s/", [path UTF8String]); + size_t cpath_end = strlen(cpath); + + DIR* dir = opendir(cpath); + if (!dir) + return result; - if (regex) + for(struct dirent* item = readdir(dir); item; item = readdir(dir)) { - result = [result filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^(id object, NSDictionary* bindings) - { - if (ra_ios_is_directory(object)) - return YES; - - return (BOOL)([regex numberOfMatchesInString:[object lastPathComponent] options:0 range:NSMakeRange(0, [[object lastPathComponent] length])] != 0); - }]]; + if (strcmp(item->d_name, ".") == 0 || strcmp(item->d_name, "..") == 0) + continue; + + cpath[cpath_end] = 0; + strcat(cpath, item->d_name); + + [result addObject:[RADirectoryItem directoryItemFromPath:cpath]]; } - result = [result sortedArrayUsingComparator:^(id left, id right) - { - const BOOL left_is_dir = ra_ios_is_directory((NSString*)left); - const BOOL right_is_dir = ra_ios_is_directory((NSString*)right); - - return (left_is_dir != right_is_dir) ? - (left_is_dir ? -1 : 1) : - ([left caseInsensitiveCompare:right]); - }]; + closedir(dir); + free(cpath); + // Filter and sort + if (regex) + { + [result filterUsingPredicate:[NSPredicate predicateWithBlock:^(RADirectoryItem* object, NSDictionary* bindings) + { + if (object.isDirectory) + return YES; + + return (BOOL)([regex numberOfMatchesInString:[object.path lastPathComponent] options:0 range:NSMakeRange(0, [[object.path lastPathComponent] length])] != 0); + }]]; + } + + [result sortUsingComparator:^(RADirectoryItem* left, RADirectoryItem* right) + { + return (left.isDirectory != right.isDirectory) ? + (left.isDirectory ? -1 : 1) : + ([left.path caseInsensitiveCompare:right.path]); + }]; + return result; }