diff options
-rw-r--r-- | Menes/Function.h | 154 | ||||
-rw-r--r-- | Menes/Menes.h | 1 | ||||
-rw-r--r-- | MobileCydia.mm | 255 |
3 files changed, 251 insertions, 159 deletions
diff --git a/Menes/Function.h b/Menes/Function.h new file mode 100644 index 0000000..f058653 --- /dev/null +++ b/Menes/Function.h @@ -0,0 +1,154 @@ +/* Cydia - iPhone UIKit Front-End for Debian APT + * Copyright (C) 2008-2013 Jay Freeman (saurik) +*/ + +/* GNU General Public License, Version 3 {{{ */ +/* + * Cydia is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Cydia is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cydia. If not, see <http://www.gnu.org/licenses/>. +**/ +/* }}} */ + +#ifndef Menes_Function_H +#define Menes_Function_H + +#include "CyteKit/UCPlatform.h" + +template <typename Result_, typename... Args_> +class Function { + private: + class Abstract { + private: + unsigned references_; + + public: + Abstract() : + references_(0) + { + } + + Abstract(const Abstract &) = delete; + Abstract &operator =(const Abstract &) = delete; + + virtual ~Abstract() { + } + + void Retain() { + ++references_; + } + + void Release() { + if (--references_ == 0) + delete this; + } + + virtual Result_ operator()(Args_... args) const = 0; + }; + + template <typename Callable_> + class Concrete : + public Abstract + { + private: + Callable_ callable_; + + public: + Concrete(const Callable_ &callable) : + callable_(callable) + { + } + + virtual Result_ operator()(Args_... args) const { + return callable_(args...); + } + }; + + private: + Abstract *abstract_; + + void Release() { + if (abstract_ != NULL) + abstract_->Release(); + } + + void Copy(Abstract *abstract) { + if (abstract != NULL) + abstract->Retain(); + Release(); + abstract_ = abstract; + } + + template <typename Callable_> + void Assign(const Callable_ &callable) { + Copy(new Concrete<Callable_>(callable)); + } + + public: + Function() : + abstract_(NULL) + { + } + + Function(decltype(nullptr)) : + Function() + { + } + + Function(const Function &function) : + abstract_(function.abstract_) + { + abstract_->Retain(); + } + + template <typename Callable_> + Function(const Callable_ &callable) : + Function() + { + Assign(callable); + } + + ~Function() { + Release(); + } + + Function &operator =(decltype(nullptr)) { + Clear(); + return *this; + } + + Function &operator =(const Function &function) { + Copy(function.abstract_); + return *this; + } + + Result_ operator()(Args_... args) const { + return (*abstract_)(args...); + } + + void Clear() { + Release(); + abstract_ = NULL; + } + + template <typename Callable_> + Function &operator =(const Callable_ &callable) { + Assign(callable); + return *this; + } + + operator bool() const { + return abstract_ != NULL; + } +}; + +#endif//Menes_Function_H diff --git a/Menes/Menes.h b/Menes/Menes.h index 861c285..360d61c 100644 --- a/Menes/Menes.h +++ b/Menes/Menes.h @@ -22,6 +22,7 @@ #ifndef Menes_Menes_H #define Menes_Menes_H +#include "Menes/Function.h" #include "Menes/ObjectHandle.h" #include "Menes/invocationWithSelector.h" diff --git a/MobileCydia.mm b/MobileCydia.mm index 386ac11..fc48972 100644 --- a/MobileCydia.mm +++ b/MobileCydia.mm @@ -1949,7 +1949,7 @@ struct ParsedPackage { @interface Package : NSObject { uint32_t era_ : 25; - uint32_t role_ : 3; + @public uint32_t role_ : 3; uint32_t essential_ : 1; uint32_t obsolete_ : 1; uint32_t ignored_ : 1; @@ -2060,12 +2060,6 @@ struct ParsedPackage { - (void) install; - (void) remove; -- (bool) isUnfilteredAndSearchedForBy:(NSArray *)query; -- (bool) isUnfilteredAndSelectedForBy:(NSString *)search; -- (bool) isInstalledAndUnfiltered:(NSNumber *)number; -- (bool) isVisibleInSection:(NSString *)section source:(Source *)source; -- (bool) isVisibleInSource:(Source *)source; - @end uint32_t PackageChangesRadix(Package *self, void *) { @@ -3149,62 +3143,6 @@ struct PackageNameOrdering : cache->MarkDelete(iterator_, true); } } -- (bool) isUnfilteredAndSearchedForBy:(NSArray *)query { - _profile(Package$isUnfilteredAndSearchedForBy) - bool value(true); - - _profile(Package$isUnfilteredAndSearchedForBy$Unfiltered) - value &= [self unfiltered]; - _end - - _profile(Package$isUnfilteredAndSearchedForBy$Match) - value &= [self matches:query]; - _end - - return value; - _end -} - -- (bool) isUnfilteredAndSelectedForBy:(NSString *)search { - if ([search length] == 0) - return false; - - _profile(Package$isUnfilteredAndSelectedForBy) - bool value(true); - - _profile(Package$isUnfilteredAndSelectedForBy$Unfiltered) - value &= [self unfiltered]; - _end - - _profile(Package$isUnfilteredAndSelectedForBy$Match) - value &= [[self name] compare:search options:MatchCompareOptions_ range:NSMakeRange(0, [search length])] == NSOrderedSame; - _end - - return value; - _end -} - -- (bool) isInstalledAndUnfiltered:(NSNumber *)number { - return ![self uninstalled] && role_ <= ([number boolValue] ? 1 : 3); -} - -- (bool) isVisibleInSection:(NSString *)name source:(Source *)source { - NSString *section([self section]); - - return ( - name == nil || - section == nil && [name length] == 0 || - [name isEqualToString:section] - ) && ( - source == nil || - [self source] == source - ) && [self visible]; -} - -- (bool) isVisibleInSource:(Source *)source { - return [self source] == source && [self visible]; -} - @end /* }}} */ /* Section Class {{{ */ @@ -6638,113 +6576,64 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @end /* }}} */ /* Filtered Package List Controller {{{ */ +typedef Function<bool, Package *> PackageFilter; +typedef Function<void, NSMutableArray *> PackageSorter; @interface FilteredPackageListController : PackageListController { - SEL filter_; - IMP imp_; - _H<NSObject> object_; - _H<NSObject> stuff_; + PackageFilter filter_; + PackageSorter sorter_; } -- (void) setObject:(id)object; -- (void) setStuff:(id)object; -- (void) setObject:(id)object andStuff:(id)stuff; - -- (void) setObject:(id)object forFilter:(SEL)filter; -- (void) setObject:(id)object andStuff:(id)stuff forFilter:(SEL)filter; - -- (SEL) filter; -- (void) setFilter:(SEL)filter; +- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(PackageFilter)filter; -- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object; +- (void) setFilter:(PackageFilter)filter; +- (void) setSorter:(PackageSorter)sorter; @end @implementation FilteredPackageListController -- (SEL) filter { - return filter_; -} - -- (void) setFilter:(SEL)filter { +- (void) setFilter:(PackageFilter)filter { @synchronized (self) { filter_ = filter; - - /* XXX: this is an unsafe optimization of doomy hell */ - Method method(class_getInstanceMethod([Package class], filter)); - _assert(method != NULL); - imp_ = method_getImplementation(method); - _assert(imp_ != NULL); -} } - -- (void) setObject:(id)object { -@synchronized (self) { - object_ = object; -} } - -- (void) setStuff:(id)stuff { -@synchronized (self) { - stuff_ = stuff; } } -- (void) setObject:(id)object andStuff:(id)stuff { +- (void) setSorter:(PackageSorter)sorter { @synchronized (self) { - object_ = object; - stuff_ = stuff; -} } - -- (void) setObject:(id)object forFilter:(SEL)filter { -@synchronized (self) { - [self setFilter:filter]; - object_ = object; -} } - -- (void) setObject:(id)object andStuff:(id)stuff forFilter:(SEL)filter { -@synchronized (self) { - [self setFilter:filter]; - object_ = object; - stuff_ = stuff; + sorter_ = sorter; } } - (NSMutableArray *) _reloadPackages { + NSMutableArray *filtered; + PackageSorter sorter; + @synchronized (database_) { era_ = [database_ era]; NSArray *packages([database_ packages]); - NSMutableArray *filtered([NSMutableArray arrayWithCapacity:[packages count]]); + filtered = [NSMutableArray arrayWithCapacity:[packages count]]; - IMP imp; - SEL filter; - _H<NSObject> object; - _H<NSObject> stuff; + PackageFilter filter; @synchronized (self) { - imp = imp_; filter = filter_; - object = object_; - stuff = stuff_; + sorter = sorter_; } _profile(PackageTable$reloadData$Filter) for (Package *package in packages) - if ([package valid] && (*reinterpret_cast<bool (*)(id, SEL, id, id)>(imp))(package, filter, object, stuff)) + if ([package valid] && filter(package)) [filtered addObject:package]; _end +} + if (sorter) + sorter(filtered); return filtered; -} } - -- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object { - if ((self = [super initWithDatabase:database title:title]) != nil) { - [self setFilter:filter]; - object_ = object; - } return self; } -- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object with:(id)stuff { +- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(PackageFilter)filter { if ((self = [super initWithDatabase:database title:title]) != nil) { [self setFilter:filter]; - object_ = object; - stuff_ = stuff; } return self; } @@ -7158,14 +7047,29 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi else title = UCLocalize("NO_SECTION"); - if ((self = [super initWithDatabase:database title:title filter:@selector(isVisibleInSection:source:) with:section with:source]) != nil) { + if ((self = [super initWithDatabase:database title:title]) != nil) { key_ = [source key]; section_ = section; } return self; } - (void) reloadData { - [super setStuff:[database_ sourceWithKey:key_]]; + Source *source([database_ sourceWithKey:key_]); + _H<NSString> name(section_); + + [self setFilter:[=](Package *package) { + NSString *section([package section]); + + return ( + name == nil || + section == nil && [name length] == 0 || + [name isEqualToString:section] + ) && ( + source == nil || + [package source] == source + ) && [package visible]; + }]; + [super reloadData]; } @@ -7664,6 +7568,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi > { _H<UISearchBar, 1> search_; BOOL searchloaded_; + bool summary_; } - (id) initWithDatabase:(Database *)database query:(NSString *)query; @@ -7694,15 +7599,51 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi } - (void) useSearch { - [self setObject:[self termsForQuery:[search_ text]] forFilter:@selector(isUnfilteredAndSearchedForBy:)]; + _H<NSArray> query([self termsForQuery:[search_ text]]); + summary_ = false; + +@synchronized (self) { + [self setFilter:[=](Package *package) { + if (![package unfiltered]) + return false; + if (![package matches:query]) + return false; + return true; + }]; + + [self setSorter:[](NSMutableArray *packages) { + [packages radixSortUsingSelector:@selector(rank)]; + }]; +} + [self clearData]; [self reloadData]; } +- (void) usePrefix:(NSString *)prefix { + _H<NSString> query(prefix); + summary_ = true; + +@synchronized (self) { + [self setFilter:[=](Package *package) { + if ([query length] == 0) + return false; + if (![package unfiltered]) + return false; + if ([[package name] compare:query options:MatchCompareOptions_ range:NSMakeRange(0, [query length])] != NSOrderedSame) + return false; + return true; + }]; + + [self setSorter:nullptr]; +} + + [self reloadData]; +} + - (void) searchBarTextDidBeginEditing:(UISearchBar *)searchBar { - [self setObject:[search_ text] forFilter:@selector(isUnfilteredAndSelectedForBy:)]; [self clearData]; - [self reloadData]; + [self usePrefix:[search_ text]]; } - (void) searchBarButtonClicked:(UISearchBar *)searchBar { @@ -7720,8 +7661,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi } - (void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)text { - [self setObject:text forFilter:@selector(isUnfilteredAndSelectedForBy:)]; - [self reloadData]; + [self usePrefix:text]; } - (bool) shouldYield { @@ -7729,31 +7669,25 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi } - (bool) shouldBlock { - return [self filter] == @selector(isUnfilteredAndSearchedForBy:); + return !summary_; } - (bool) isSummarized { - return [self filter] == @selector(isUnfilteredAndSelectedForBy:); + return summary_; } - (bool) showsSections { return false; } -- (NSMutableArray *) _reloadPackages { - NSMutableArray *packages([super _reloadPackages]); - if ([self filter] == @selector(isUnfilteredAndSearchedForBy:)) - [packages radixSortUsingSelector:@selector(rank)]; - return packages; -} - - (id) initWithDatabase:(Database *)database query:(NSString *)query { - if ((self = [super initWithDatabase:database title:UCLocalize("SEARCH") filter:@selector(isUnfilteredAndSearchedForBy:) with:[self termsForQuery:query]])) { + if ((self = [super initWithDatabase:database title:UCLocalize("SEARCH")])) { search_ = [[[UISearchBar alloc] init] autorelease]; [search_ setDelegate:self]; if (query != nil) [search_ setText:query]; + [self useSearch]; } return self; } @@ -7782,13 +7716,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi } - (void) reloadData { - id object([search_ text]); - if ([self filter] == @selector(isUnfilteredAndSearchedForBy:)) - object = [self termsForQuery:object]; - - [self setObject:object]; [self resetCursor]; - [super reloadData]; } @@ -7991,14 +7919,24 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi return [NSURL URLWithString:@"cydia://installed"]; } +- (void) useFilter:(UISegmentedControl *)segmented { + bool simple([segmented selectedSegmentIndex] == 0); + +@synchronized (self) { + [self setFilter:[=](Package *package) { + return ![package uninstalled] && package->role_ <= (simple ? 1 : 3); + }]; +} } + - (id) initWithDatabase:(Database *)database { - if ((self = [super initWithDatabase:database title:UCLocalize("INSTALLED") filter:@selector(isInstalledAndUnfiltered:) with:[NSNumber numberWithBool:YES]]) != nil) { + if ((self = [super initWithDatabase:database title:UCLocalize("INSTALLED")]) != nil) { UISegmentedControl *segmented([[[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:UCLocalize("SIMPLE"), UCLocalize("EXPERT"), nil]] autorelease]); [segmented setSelectedSegmentIndex:0]; [segmented setSegmentedControlStyle:UISegmentedControlStyleBar]; [[self navigationItem] setTitleView:segmented]; [segmented addTarget:self action:@selector(modeChanged:) forEvents:UIControlEventValueChanged]; + [self useFilter:segmented]; [self queueStatusDidChange]; } return self; @@ -8026,8 +7964,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi } - (void) modeChanged:(UISegmentedControl *)segmented { - bool simple([segmented selectedSegmentIndex] == 0); - [self setObject:[NSNumber numberWithBool:simple]]; + [self useFilter:segmented]; [self reloadData]; } |