/* Insertion Sort {{{ */
-CFIndex SKBSearch_(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) {
+template <typename Type_>
+size_t CFBSearch_(const Type_ &element, const void *list, size_t count, CFComparisonResult (*comparator)(Type_, Type_, void *), void *context) {
const char *ptr = (const char *)list;
while (0 < count) {
- CFIndex half = count / 2;
- const char *probe = ptr + elementSize * half;
- CFComparisonResult cr = comparator(element, probe, context);
- if (0 == cr) return (probe - (const char *)list) / elementSize;
- ptr = (cr < 0) ? ptr : probe + elementSize;
+ size_t half = count / 2;
+ const char *probe = ptr + sizeof(Type_) * half;
+ CFComparisonResult cr = comparator(element, * (const Type_ *) probe, context);
+ if (0 == cr) return (probe - (const char *)list) / sizeof(Type_);
+ ptr = (cr < 0) ? ptr : probe + sizeof(Type_);
count = (cr < 0) ? half : (half + (count & 1) - 1);
}
- return (ptr - (const char *)list) / elementSize;
+ return (ptr - (const char *)list) / sizeof(Type_);
}
-CFIndex CFBSearch_(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) {
- const char *ptr = (const char *)list;
- while (0 < count) {
- CFIndex half = count / 2;
- const char *probe = ptr + elementSize * half;
- CFComparisonResult cr = comparator(element, probe, context);
- if (0 == cr) return (probe - (const char *)list) / elementSize;
- ptr = (cr < 0) ? ptr : probe + elementSize;
- count = (cr < 0) ? half : (half + (count & 1) - 1);
- }
- return (ptr - (const char *)list) / elementSize;
-}
-
-void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFComparatorFunction comparator, void *context) {
- if (range.length == 0)
+template <typename Type_>
+void CYArrayInsertionSortValues(Type_ *values, size_t length, CFComparisonResult (*comparator)(Type_, Type_, void *), void *context) {
+ if (length == 0)
return;
- const void **values(new const void *[range.length]);
- CFArrayGetValues(array, range, values);
#if HistogramInsertionSort > 0
- uint32_t total(0), *offsets(new uint32_t[range.length]);
+ uint32_t total(0), *offsets(new uint32_t[length]);
#endif
- for (CFIndex index(1); index != range.length; ++index) {
- const void *value(values[index]);
- //CFIndex correct(SKBSearch_(&value, sizeof(const void *), values, index, comparator, context));
- CFIndex correct(index);
+ for (size_t index(1); index != length; ++index) {
+ Type_ value(values[index]);
+#if 0
+ size_t correct(CFBSearch_(value, values, index, comparator, context));
+#else
+ size_t correct(index);
while (comparator(value, values[correct - 1], context) == kCFCompareLessThan) {
#if HistogramInsertionSort > 1
NSLog(@"%@ < %@", value, values[correct - 1]);
#endif
if (--correct == 0)
break;
+ if (index - correct >= 8) {
+ correct = CFBSearch_(value, values, correct, comparator, context);
+ break;
+ }
}
+#endif
if (correct != index) {
size_t offset(index - correct);
#if HistogramInsertionSort
}
}
- CFArrayReplaceValues(array, range, values, range.length);
- delete [] values;
-
#if HistogramInsertionSort > 0
- for (CFIndex index(0); index != range.length; ++index)
+ for (size_t index(0); index != range.length; ++index)
if (offsets[index] != 0)
NSLog(@"Insertion Displacement [%u]: %u", index, offsets[index]);
NSLog(@"Average Insertion Displacement: %f", double(total) / range.length);
SourceMap sourceMap_;
_H<NSMutableArray> sourceList_;
- CFMutableArrayRef packages_;
+ _H<NSArray> packages_;
_transient NSObject<DatabaseDelegate> *delegate_;
_transient NSObject<ProgressDelegate> *progress_;
}
//printf("Set(%s, %s)\n", fetch ? "true" : "false", uri.c_str());
- [database_ setFetch:fetch forURI:uri.c_str()];
+
+ auto slash(uri.rfind('/'));
+ if (slash != std::string::npos)
+ [database_ setFetch:fetch forURI:uri.substr(0, slash).c_str()];
}
_finline void Set(bool fetch, pkgAcquire::Item *item) {
_profile(Source$setMetaIndex$DescURI)
for (pkgAcquire::ItemIterator item(acquire.ItemsBegin()); item != acquire.ItemsEnd(); item++) {
std::string file((*item)->DescURI());
- files_.insert(file);
- if (file.length() < sizeof("Packages.bz2") || file.substr(file.length() - sizeof("Packages.bz2")) != "/Packages.bz2")
+ auto slash(file.rfind('/'));
+ if (slash == std::string::npos)
continue;
- file = file.substr(0, file.length() - 4);
- files_.insert(file);
- files_.insert(file + ".gz");
- files_.insert(file + "Index");
+ files_.insert(file.substr(0, slash));
}
_end
}
- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database;
++ (Package *) newPackageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database;
+
+ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database;
- (pkgCache::PkgIterator) iterator;
_end } return self;
}
-+ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database {
++ (Package *) newPackageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database {
pkgCache::VerIterator version;
_profile(Package$packageWithIterator$GetCandidateVer)
];
_end
- _profile(Package$packageWithIterator$Autorelease)
- package = [package autorelease];
- _end
-
return package;
}
+// XXX: just in case a Cydia extension is using this (I bet this is unlikely, though, due to CYPool?)
++ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database {
+ return [[self newPackageWithIterator:iterator withZone:zone inPool:pool database:database] autorelease];
+}
+
- (pkgCache::PkgIterator) iterator {
return iterator_;
}
}
- (void) setIndex:(size_t)index {
- if (metadata_->index_ != index)
- metadata_->index_ = index;
+ if (metadata_->index_ != index + 1)
+ metadata_->index_ = index + 1;
}
- (CYString &) cyname {
}
- (void) releasePackages {
- CFArrayApplyFunction(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast<CFArrayApplierFunction>(&CFRelease), NULL);
- CFArrayRemoveAllValues(packages_);
+ packages_ = nil;
}
- (bool) hasPackages {
- return CFArrayGetCount(packages_) != 0;
+ return [packages_ count] != 0;
}
- (void) dealloc {
, "any"
#endif
));
- return iterator.end() ? nil : [Package packageWithIterator:iterator withZone:NULL inPool:NULL database:self];
+ return iterator.end() ? nil : [[Package newPackageWithIterator:iterator withZone:NULL inPool:NULL database:self] autorelease];
} }
- (id) init {
zone_ = NSCreateZone(1024 * 1024, 256 * 1024, NO);
- size_t capacity(MetaFile_->active_);
- if (capacity == 0)
- capacity = 16384;
- else
- capacity += 1024;
-
- packages_ = CFArrayCreateMutable(kCFAllocatorDefault, capacity, NULL);
sourceList_ = [NSMutableArray arrayWithCapacity:16];
int fds[2];
}
- (NSArray *) packages {
- return (NSArray *) packages_;
+ return packages_;
}
- (NSArray *) sources {
}
{
- /*std::vector<Package *> packages;
- packages.reserve(std::max(10000U, [packages_ count] + 1000));
- packages_ = nil;*/
+ size_t capacity(MetaFile_->active_);
+ if (capacity == 0)
+ capacity = 128*1024;
+ else
+ capacity += 1024;
+ std::vector<Package *> packages;
+ packages.reserve(capacity);
+ size_t lost(0);
+
+ size_t last(0);
_profile(reloadDataWithInvocation$packageWithIterator)
for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator)
- if (Package *package = [Package packageWithIterator:iterator withZone:zone_ inPool:&pool_ database:self])
- //packages.push_back(package);
- CFArrayAppendValue(packages_, CFRetain(package));
+ if (Package *package = [Package newPackageWithIterator:iterator withZone:zone_ inPool:&pool_ database:self]) {
+ if (unsigned index = package.metadata->index_) {
+ --index;
+ if (packages.size() == index) {
+ packages.push_back(package);
+ } else if (packages.size() <= index) {
+ packages.resize(index + 1, nil);
+ packages[index] = package;
+ continue;
+ } else {
+ std::swap(package, packages[index]);
+ if (package != nil)
+ goto lost;
+ if (last != index)
+ continue;
+ }
+ } else lost: {
+ ++lost;
+ if (last == packages.size()) {
+ packages.push_back(package);
+ ++last;
+ } else {
+ packages[last] = package;
+ ++last;
+ }
+ }
+
+ for (; last != packages.size(); ++last)
+ if (packages[last] == nil)
+ break;
+ }
_end
+ for (size_t next(last + 1); last != packages.size(); ++last, ++next) {
+ while (true) {
+ if (next == packages.size())
+ goto done;
+ if (packages[next] != nil)
+ break;
+ ++next;
+ }
+
+ std::swap(packages[last], packages[next]);
+ } done:;
- /*if (packages.empty())
- packages_ = [[NSArray alloc] init];
- else
- packages_ = [[NSArray alloc] initWithObjects:&packages.front() count:packages.size()];
- _trace();*/
+ packages.resize(last);
- _profile(reloadDataWithInvocation$radix$8)
- [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(8)];
- _end
+ if (lost > 128) {
+ NSLog(@"lost = %zu", lost);
- _profile(reloadDataWithInvocation$radix$4)
- [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(4)];
- _end
+ _profile(reloadDataWithInvocation$radix$8)
+ CYRadixSortUsingFunction(packages.data(), packages.size(), reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix), reinterpret_cast<void *>(8));
+ _end
- _profile(reloadDataWithInvocation$radix$0)
- [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(0)];
- _end
+ _profile(reloadDataWithInvocation$radix$4)
+ CYRadixSortUsingFunction(packages.data(), packages.size(), reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix), reinterpret_cast<void *>(4));
+ _end
+
+ _profile(reloadDataWithInvocation$radix$0)
+ CYRadixSortUsingFunction(packages.data(), packages.size(), reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix), reinterpret_cast<void *>(0));
+ _end
+ }
_profile(reloadDataWithInvocation$insertion)
- CFArrayInsertionSortValues(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
+ CYArrayInsertionSortValues(packages.data(), packages.size(), &PackageNameCompare, NULL);
_end
+ packages_ = [[[NSArray alloc] initWithObjects:packages.data() count:packages.size()] autorelease];
+
/*_profile(reloadDataWithInvocation$CFQSortArray)
CFQSortArray(&packages.front(), packages.size(), sizeof(packages.front()), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare_), NULL);
_end*/
[packages_ sortUsingFunction:reinterpret_cast<NSComparisonResult (*)(id, id, void *)>(&PackageNameCompare) context:NULL];
_end*/
-
- size_t count(CFArrayGetCount(packages_));
- MetaFile_->active_ = count;
- for (size_t index(0); index != count; ++index)
- [(Package *) CFArrayGetValueAtIndex(packages_, index) setIndex:index];
+ MetaFile_->active_ = packages.size();
+ for (size_t index(0), count(packages.size()); index != count; ++index) {
+ auto package(packages[index]);
+ [package setIndex:index];
+ [package release];
+ }
}
} }
#if !AlwaysReload
- (void) _customButtonClicked {
- if (commercial_ && [package_ uninstalled])
+ if (commercial_ && self.isLoading && [package_ uninstalled])
return [self reloadURLWithCache:NO];
size_t count(buttons_.size());
}
if (Languages_ != nil)
- for (NSString *language : Languages_) {
+ for (NSString *locale : Languages_) {
+ auto components([NSLocale componentsFromLocaleIdentifier:locale]);
+ NSString *language([components objectForKey:(id)kCFLocaleLanguageCode]);
+ if (NSString *script = [components objectForKey:(id)kCFLocaleScriptCode])
+ language = [NSString stringWithFormat:@"%@-%@", language, script];
languages += [language UTF8String];
languages += ",";
}