}
- (id) yieldToSelector:(SEL)selector withObject:(id)object {
- /*return [self performSelector:selector withObject:object];*/
-
volatile bool stopped(false);
NSMutableArray *context([NSMutableArray arrayWithObjects:
cache_ = reinterpret_cast<CFStringRef>(CFRetain(rhs.cache_));
}
+ void copy(apr_pool_t *pool) {
+ char *temp(reinterpret_cast<char *>(apr_palloc(pool, size_ + 1)));
+ memcpy(temp, data_, size_);
+ temp[size_] = '\0';
+ data_ = temp;
+ }
+
void set(apr_pool_t *pool, const char *data, size_t size) {
if (size == 0)
clear();
else {
clear_();
- char *temp(reinterpret_cast<char *>(apr_palloc(pool, size + 1)));
- memcpy(temp, data, size);
- temp[size] = '\0';
- data_ = temp;
+ data_ = const_cast<char *>(data);
size_ = size;
+
+ if (pool != NULL)
+ copy(pool);
}
}
static _finline const char *StripVersion_(const char *version) {
const char *colon(strchr(version, ':'));
- if (colon != NULL)
- version = colon + 1;
- return version;
+ return colon == NULL ? version : colon + 1;
}
NSString *LocalizeSection(NSString *section) {
struct PackageValue :
Cytore::Block
{
- Cytore::Offset<void> reserved_;
Cytore::Offset<PackageValue> next_;
uint32_t index_ : 23;
struct MetaValue :
Cytore::Block
{
- Cytore::Offset<void> reserved_;
Cytore::Offset<PackageValue> packages_[1 << 16];
};
static Cytore::File<MetaValue> MetaFile_;
// }}}
// Cytore Helper Functions {{{
-static PackageValue *PackageFind(const char *name, size_t length, Cytore::Offset<PackageValue> *cache = NULL) {
+static PackageValue *PackageFind(const char *name, size_t length) {
SplitHash nhash = { hashlittle(name, length) };
PackageValue *metadata;
}
}
- if (cache != NULL)
- *cache = *offset;
-
return metadata;
}
metadata->first_ = time;
}
+ bool versioned(false);
+
if (NSDate *date = [package objectForKey:@"LastSeen"]) {
time_t time([date timeIntervalSince1970]);
if (metadata->last_ < time || metadata->last_ == 0) {
metadata->last_ = time;
- goto last;
+ versioned = true;
}
- } else if (metadata->last_ == 0) last: {
- NSString *version([package objectForKey:@"LastVersion"]);
- if (CFStringGetCString((CFStringRef) version, buffer, sizeof(buffer), kCFStringEncodingUTF8)) {
- size_t length(strlen(buffer));
- uint16_t vhash(hashlittle(buffer, length));
+ } else if (metadata->last_ == 0) {
+ metadata->last_ = metadata->first_;
+ if (metadata->version_[0] == '\0')
+ versioned = true;
+ }
- size_t capped(std::min<size_t>(8, length));
- char *latest(buffer + length - capped);
+ if (versioned)
+ if (NSString *version = [package objectForKey:@"LastVersion"])
+ if (CFStringGetCString((CFStringRef) version, buffer, sizeof(buffer), kCFStringEncodingUTF8)) {
+ size_t length(strlen(buffer));
+ uint16_t vhash(hashlittle(buffer, length));
- strncpy(metadata->version_, latest, sizeof(metadata->version_));
- metadata->vhash_ = vhash;
- }
- }
+ size_t capped(std::min<size_t>(8, length));
+ char *latest(buffer + length - capped);
+
+ strncpy(metadata->version_, latest, sizeof(metadata->version_));
+ metadata->vhash_ = vhash;
+ }
}
// }}}
@end
/* }}} */
/* Package Class {{{ */
+struct ParsedPackage {
+ CYString tagline_;
+
+ CYString icon_;
+
+ CYString depiction_;
+ CYString homepage_;
+
+ CYString sponsor_;
+ CYString author_;
+
+ CYString bugs_;
+ CYString support_;
+};
+
@interface Package : NSObject {
- unsigned era_;
+ uint32_t era_ : 29;
+ uint32_t essential_ : 1;
+ uint32_t obsolete_ : 1;
+ uint32_t ignored_ : 1;
+
apr_pool_t *pool_;
+ _transient Database *database_;
+
pkgCache::VerIterator version_;
pkgCache::PkgIterator iterator_;
- _transient Database *database_;
pkgCache::VerFileIterator file_;
- Source *source_;
- bool parsed_;
-
- CYString section_;
- _transient NSString *section$_;
- bool essential_;
- bool obsolete_;
+ CYString id_;
+ CYString name_;
CYString latest_;
CYString installed_;
- CYString id_;
- CYString name_;
- CYString tagline_;
- CYString icon_;
- CYString depiction_;
- CYString homepage_;
+ CYString section_;
+ _transient NSString *section$_;
- CYString sponsor_;
- Address *sponsor$_;
+ Source *source_;
- CYString author_;
- Address *author$_;
+ PackageValue *metadata_;
+ ParsedPackage *parsed_;
- CYString bugs_;
- CYString support_;
NSMutableArray *tags_;
NSString *role_;
-
- Cytore::Offset<PackageValue> metadata_;
-
- bool ignored_;
}
- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database;
- (NSArray *) purposes;
- (bool) isCommercial;
+- (void) setIndex:(size_t)index;
+
- (CYString &) cyname;
- (uint32_t) compareBySection:(NSArray *)sections;
value.bits.ignored = [self ignored] ? 0 : 1;
value.bits.upgradable = 1;
} else {
- value.bits.timestamp = static_cast<uint32_t>([self seen]) >> 2;
+ value.bits.timestamp = [self seen] >> 2;
value.bits.ignored = 0;
value.bits.upgradable = 0;
}
return _not(uint32_t) - value.key;
}
-_finline static void Stifle(uint8_t &value) {
-}
-
uint32_t PackagePrefixRadix(Package *self, void *context) {
size_t offset(reinterpret_cast<size_t>(context));
CYString &name([self cyname]);
uint8_t data[4];
- // 0.607997
-
if (offset == 0 && zeros != 0) {
memset(data, '0', zeros);
memcpy(data + zeros, text, 4 - zeros);
}
- (void) dealloc {
+ if (parsed_ != NULL)
+ delete parsed_;
+
if (source_ != nil)
[source_ release];
- if (sponsor$_ != nil)
- [sponsor$_ release];
- if (author$_ != nil)
- [author$_ release];
if (tags_ != nil)
[tags_ release];
if (role_ != nil)
}
- (void) parse {
- if (parsed_)
+ if (parsed_ != NULL)
return;
- parsed_ = true;
- if (file_.end())
+@synchronized (database_) {
+ if ([database_ era] != era_ || file_.end())
return;
+ ParsedPackage *parsed(new ParsedPackage);
+ parsed_ = parsed;
+
_profile(Package$parse)
pkgRecords::Parser *parser;
const char *name_;
CYString *value_;
} names[] = {
- {"icon", &icon_},
- {"depiction", &depiction_},
- {"homepage", &homepage_},
+ {"icon", &parsed->icon_},
+ {"depiction", &parsed->depiction_},
+ {"homepage", &parsed->homepage_},
{"website", &website},
- {"bugs", &bugs_},
- {"support", &support_},
- {"sponsor", &sponsor_},
- {"author", &author_},
+ {"bugs", &parsed->bugs_},
+ {"support", &parsed->support_},
+ {"sponsor", &parsed->sponsor_},
+ {"author", &parsed->author_},
};
for (size_t i(0); i != sizeof(names) / sizeof(names[0]); ++i) {
stop = end;
while (stop != start && stop[-1] == '\r')
--stop;
- tagline_.set(pool_, start, stop - start);
+ parsed->tagline_.set(pool_, start, stop - start);
}
_end
_profile(Package$parse$Retain)
- if (homepage_.empty())
- homepage_ = website;
- if (homepage_ == depiction_)
- homepage_.clear();
+ if (parsed->homepage_.empty())
+ parsed->homepage_ = website;
+ if (parsed->homepage_ == parsed->depiction_)
+ parsed->homepage_.clear();
_end
_end
-}
+} }
- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database {
if ((self = [super init]) != nil) {
_profile(Package$initWithVersion)
- era_ = [database era];
pool_ = pool;
- version_ = version;
-
- _profile(Package$initWithVersion$ParentPkg)
- iterator_ = version.ParentPkg();
- _end
-
database_ = database;
+ era_ = [database era];
- _profile(Package$initWithVersion$Latest)
- latest_.set(pool_, StripVersion_(version_.VerStr()));
- _end
+ version_ = version;
- pkgCache::VerIterator current;
- _profile(Package$initWithVersion$Versions)
- current = iterator_.CurrentVer();
- if (!current.end())
- installed_.set(pool_, StripVersion_(current.VerStr()));
+ pkgCache::PkgIterator iterator(version.ParentPkg());
+ iterator_ = iterator;
+ _profile(Package$initWithVersion$Version)
if (!version_.end())
file_ = version_.FileList();
else {
}
_end
- _profile(Package$initWithVersion$Name)
- id_.set(pool_, iterator_.Name());
- name_.set(pool, iterator_.Display());
+ _profile(Package$initWithVersion$Cache)
+ id_.set(NULL, iterator.Name());
+ name_.set(NULL, iterator.Display());
+
+ latest_.set(NULL, StripVersion_(version_.VerStr()));
+
+ pkgCache::VerIterator current(iterator.CurrentVer());
+ if (!current.end())
+ installed_.set(NULL, StripVersion_(current.VerStr()));
_end
- _profile(Package$initWithVersion$lowercaseString)
+ _profile(Package$initWithVersion$Lower)
+ // XXX: do not use tolower() as this is not locale-specific? :(
char *data(id_.data());
for (size_t i(0), e(id_.size()); i != e; ++i)
- // XXX: do not use tolower() as this is not locale-specific? :(
- data[i] |= 0x20;
+ if ((data[i] & 0x20) == 0) {
+ id_.copy(pool);
+ data = id_.data();
+ for (; i != e; ++i)
+ data[i] |= 0x20;
+ break;
+ }
_end
_profile(Package$initWithVersion$Tags)
- pkgCache::TagIterator tag(iterator_.TagList());
+ pkgCache::TagIterator tag(iterator.TagList());
if (!tag.end()) {
tags_ = [[NSMutableArray alloc] initWithCapacity:8];
do {
const char *name(tag.Name());
[tags_ addObject:[(NSString *)CYStringCreate(name) autorelease]];
+
if (role_ == nil && strncmp(name, "role::", 6) == 0 /*&& strcmp(name, "role::leaper") != 0*/)
role_ = (NSString *) CYStringCreate(name + 6);
+
+ if (strncmp(name, "cydia::", 7) == 0) {
+ if (strcmp(name + 7, "essential") == 0)
+ essential_ = true;
+ else if (strcmp(name + 7, "obsolete") == 0)
+ obsolete_ = true;
+ }
+
++tag;
} while (!tag.end());
}
_end
_profile(Package$initWithVersion$Metadata)
- PackageValue *metadata(PackageFind(id_.data(), id_.size(), &metadata_));
+ PackageValue *metadata(PackageFind(id_.data(), id_.size()));
+ metadata_ = metadata;
const char *latest(version_.VerStr());
size_t length(strlen(latest));
if (metadata->first_ == 0)
metadata->first_ = now_;
+ if (metadata->last_ == 0)
+ metadata->last_ = metadata->first_;
+
if (metadata->vhash_ != vhash || strncmp(metadata->version_, latest, sizeof(metadata->version_)) != 0) {
- metadata->last_ = now_;
+ if (metadata->version_[0] != '\0')
+ metadata->last_ = now_;
strncpy(metadata->version_, latest, sizeof(metadata->version_));
metadata->vhash_ = vhash;
- } else if (metadata->last_ == 0)
- metadata->last_ = metadata->first_;
+ }
_end
_profile(Package$initWithVersion$Section)
- section_.set(pool_, iterator_.Section());
+ section_.set(NULL, iterator.Section());
_end
- _profile(Package$initWithVersion$hasTag)
- obsolete_ = [self hasTag:@"cydia::obsolete"];
- essential_ = ((iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES) || [self hasTag:@"cydia::essential"];
+ _profile(Package$initWithVersion$Flags)
+ essential_ |= ((iterator->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES);
+ ignored_ = iterator->SelectedState == pkgCache::State::Hold;
_end
-
- ignored_ = iterator_->SelectedState == pkgCache::State::Hold;
_end } return self;
}
if (version.end())
return nil;
- return [[[Package alloc]
- initWithVersion:version
- withZone:zone
- inPool:pool
- database:database
- ] autorelease];
+ Package *package;
+
+ _profile(Package$packageWithIterator$Allocate)
+ package = [Package allocWithZone:zone];
+ _end
+
+ _profile(Package$packageWithIterator$Initialize)
+ package = [package
+ initWithVersion:version
+ withZone:zone
+ inPool:pool
+ database:database
+ ];
+ _end
+
+ _profile(Package$packageWithIterator$Autorelease)
+ package = [package autorelease];
+ _end
+
+ return package;
}
- (pkgCache::PkgIterator) iterator {
} }
- (NSString *) shortDescription {
- return tagline_;
+ return parsed_ == NULL ? nil : static_cast<NSString *>(parsed_->tagline_);
}
- (unichar) index {
}
- (PackageValue *) metadata {
- return &MetaFile_.Get(metadata_);
+ return metadata_;
}
- (time_t) seen {
NSString *section = [self simpleSection];
UIImage *icon(nil);
- if (!icon_.empty())
- if ([static_cast<id>(icon_) hasPrefix:@"file:///"])
- // XXX: correct escaping
- icon = [UIImage imageAtPath:[static_cast<id>(icon_) substringFromIndex:7]];
+ if (parsed_ != NULL)
+ if (NSString *href = parsed_->icon_)
+ if ([href hasPrefix:@"file:///"])
+ // XXX: correct escaping
+ icon = [UIImage imageAtPath:[href substringFromIndex:7]];
if (icon == nil) if (section != nil)
icon = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/Sections/%@.png", App_, section]];
if (icon == nil) if (Source *source = [self source]) if (NSString *dicon = [source defaultIcon])
}
- (NSString *) homepage {
- return homepage_;
+ return parsed_ == NULL ? nil : static_cast<NSString *>(parsed_->homepage_);
}
- (NSString *) depiction {
- return !depiction_.empty() ? depiction_ : [[self source] depictionForPackage:id_];
+ return parsed_ != NULL && !parsed_->depiction_.empty() ? parsed_->depiction_ : [[self source] depictionForPackage:id_];
}
- (Address *) sponsor {
- if (sponsor$_ == nil) {
- if (sponsor_.empty())
- return nil;
- sponsor$_ = [[Address addressWithString:sponsor_] retain];
- } return sponsor$_;
+ return parsed_ == NULL || parsed_->sponsor_.empty() ? nil : [Address addressWithString:parsed_->sponsor_];
}
- (Address *) author {
- if (author$_ == nil) {
- if (author_.empty())
- return nil;
- author$_ = [[Address addressWithString:author_] retain];
- } return author$_;
+ return parsed_ == NULL || parsed_->author_.empty() ? nil : [Address addressWithString:parsed_->author_];
}
- (NSString *) support {
- return !bugs_.empty() ? bugs_ : [[self source] supportForPackage:id_];
+ return parsed_ != NULL && !parsed_->bugs_.empty() ? parsed_->bugs_ : [[self source] supportForPackage:id_];
}
- (NSArray *) files {
return [self hasTag:@"cydia::commercial"];
}
+- (void) setIndex:(size_t)index {
+ if (metadata_->index_ != index)
+ metadata_->index_ = index;
+}
+
- (CYString &) cyname {
return name_.empty() ? id_ : name_;
}
//[packages_ sortUsingFunction:reinterpret_cast<NSComparisonResult (*)(id, id, void *)>(&PackageNameCompare) context:NULL];
_trace();
+
+ size_t count(CFArrayGetCount(packages_));
+ for (size_t index(0); index != count; ++index)
+ [(Package *) CFArrayGetValueAtIndex(packages_, index) setIndex:index];
+
+ _trace();
}
} } CYPoolEnd() _trace(); }
}
- (void) onSwitch:(id)sender {
- NSMutableDictionary *metadata = [Sections_ objectForKey:basic_];
+ NSMutableDictionary *metadata([Sections_ objectForKey:basic_]);
if (metadata == nil) {
metadata = [NSMutableDictionary dictionaryWithCapacity:2];
[Sections_ setObject:metadata forKey:basic_];
}
- Changed_ = true;
[metadata setObject:[NSNumber numberWithBool:([switch_ isOn] == NO)] forKey:@"Hidden"];
+ Changed_ = true;
}
- (void) setSection:(Section *)section editing:(BOOL)editing {
nil];
[Metadata_ setObject:Settings_ forKey:@"Settings"];
-
Changed_ = true;
if (rolling)
- (void) setPage:(CYViewController *)page;
- (void) loadData;
+// XXX: I hate prototypes
+- (id) queueBadgeController;
+
@end
static _finline void _setHomePage(Cydia *self) {
}
- (void) _saveConfig {
+ _trace();
+ MetaFile_.Sync();
+ _trace();
+
if (Changed_) {
- _trace();
NSString *error(nil);
+
if (NSData *data = [NSPropertyListSerialization dataFromPropertyList:Metadata_ format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error]) {
_trace();
NSError *error(nil);
if (![data writeToFile:@"/var/lib/cydia/metadata.plist" options:NSAtomicWrite error:&error])
NSLog(@"failure to save metadata data: %@", error);
_trace();
+
+ Changed_ = false;
} else {
NSLog(@"failure to serialize metadata: %@", error);
- return;
}
-
- Changed_ = false;
}
}
[search_ reloadData];
[(CYNavigationController *)[tabbar_ selectedViewController] reloadData];
+
+ [queueDelegate_ queueStatusDidChange];
+ [[[self queueBadgeController] tabBarItem] setBadgeValue:(Queuing_ ? UCLocalize("Q_D") : nil)];
}
- (int)indexOfTabWithTag:(int)tag {
}
- (void) confirmWithNavigationController:(UINavigationController *)navigation {
+ Queuing_ = false;
+
ProgressController *progress = [[[ProgressController alloc] initWithDatabase:database_ delegate:self] autorelease];
if (navigation != nil) {
@synchronized (self) {
if (clear) {
[database_ clear];
-
- // Stop queuing.
Queuing_ = false;
- [[[self queueBadgeController] tabBarItem] setBadgeValue:nil];
} else {
- // Start queuing.
Queuing_ = true;
- [[[self queueBadgeController] tabBarItem] setBadgeValue:UCLocalize("Q_D")];
}
[self _updateData];
- [queueDelegate_ queueStatusDidChange];
}
}
}
- (void) applicationDidFinishLaunching:(id)unused {
+_trace();
[CYBrowserController _initialize];
[NSURLProtocol registerClass:[CydiaURLProtocol class]];