+ _profile(Package$initWithIterator$Installed)
+ installed_ = [StripVersion(installed) retain];
+ _end
+
+ _profile(Package$initWithIterator$File)
+ if (!version_.end())
+ file_ = version_.FileList();
+ else {
+ pkgCache &cache([database_ cache]);
+ file_ = pkgCache::VerFileIterator(cache, cache.VerFileP);
+ }
+ _end
+
+ _profile(Package$initWithIterator$Name)
+ id_ = [[NSString stringWithUTF8String:iterator_.Name()] retain];
+ _end
+
+ if (!file_.end())
+ _profile(Package$initWithIterator$Parse)
+ pkgRecords::Parser *parser;
+
+ _profile(Package$initWithIterator$Parse$Lookup)
+ parser = &[database_ records]->Lookup(file_);
+ _end
+
+ const char *begin, *end;
+ parser->GetRec(begin, end);
+
+ NSString *website(nil);
+ NSString *sponsor(nil);
+ NSString *author(nil);
+ NSString *tag(nil);
+
+ struct {
+ const char *name_;
+ NSString **value_;
+ } names[] = {
+ {"name", &name_},
+ {"icon", &icon_},
+ {"depiction", &depiction_},
+ {"homepage", &homepage_},
+ {"website", &website},
+ {"support", &support_},
+ {"sponsor", &sponsor},
+ {"author", &author},
+ {"tag", &tag},
+ };
+
+ while (begin != end)
+ if (*begin == '\n') {
+ ++begin;
+ continue;
+ } else if (isblank(*begin)) next: {
+ begin = static_cast<char *>(memchr(begin + 1, '\n', end - begin - 1));
+ if (begin == NULL)
+ break;
+ } else if (const char *colon = static_cast<char *>(memchr(begin, ':', end - begin))) {
+ const char *name(begin);
+ size_t size(colon - begin);
+
+ begin = static_cast<char *>(memchr(begin, '\n', end - begin));
+
+ {
+ const char *stop(begin == NULL ? end : begin);
+ while (stop[-1] == '\r')
+ --stop;
+ while (++colon != stop && isblank(*colon));
+
+ for (size_t i(0); i != sizeof(names) / sizeof(names[0]); ++i)
+ if (strncasecmp(names[i].name_, name, size) == 0) {
+ NSString *value;
+
+ _profile(Package$initWithIterator$Parse$Value)
+ value = [NSString stringWithUTF8Bytes:colon length:(stop - colon)];
+ _end
+
+ *names[i].value_ = value;
+ break;
+ }
+ }
+
+ if (begin == NULL)
+ break;
+ ++begin;
+ } else goto next;
+
+ _profile(Package$initWithIterator$Parse$Retain)
+ if (name_ != nil)
+ name_ = [name_ retain];
+ _profile(Package$initWithIterator$Parse$Tagline)
+ tagline_ = [[NSString stringWithUTF8String:parser->ShortDesc().c_str()] retain];
+ _end
+ if (icon_ != nil)
+ icon_ = [icon_ retain];
+ if (depiction_ != nil)
+ depiction_ = [depiction_ retain];
+ if (homepage_ == nil)
+ homepage_ = website;
+ if ([homepage_ isEqualToString:depiction_])
+ homepage_ = nil;
+ if (homepage_ != nil)
+ homepage_ = [homepage_ retain];
+ if (sponsor != nil)
+ sponsor_ = [[Address addressWithString:sponsor] retain];
+ if (author != nil)
+ author_ = [[Address addressWithString:author] retain];
+ if (tag != nil)
+ tags_ = [[tag componentsSeparatedByString:@", "] retain];
+ _end
+ _end
+
+ _profile(Package$initWithIterator$Tags)
+ if (tags_ != nil)
+ for (NSString *tag in tags_)
+ if ([tag hasPrefix:@"role::"]) {
+ role_ = [[tag substringFromIndex:6] retain];
+ break;
+ }
+ _end
+
+ NSString *solid(latest == nil ? installed : latest);
+ bool changed(false);
+
+ NSString *key([id_ lowercaseString]);
+
+ _profile(Package$initWithIterator$Metadata)
+ NSMutableDictionary *metadata = [Packages_ objectForKey:key];
+ if (metadata == nil) {
+ metadata = [[NSMutableDictionary dictionaryWithObjectsAndKeys:
+ now_, @"FirstSeen",
+ nil] mutableCopy];
+
+ if (solid != nil)
+ [metadata setObject:solid forKey:@"LastVersion"];
+ changed = true;
+ } else {
+ NSDate *first([metadata objectForKey:@"FirstSeen"]);
+ NSDate *last([metadata objectForKey:@"LastSeen"]);
+ NSString *version([metadata objectForKey:@"LastVersion"]);
+
+ if (first == nil) {
+ first = last == nil ? now_ : last;
+ [metadata setObject:first forKey:@"FirstSeen"];
+ changed = true;
+ }
+
+ if (solid != nil)
+ if (version == nil) {
+ [metadata setObject:solid forKey:@"LastVersion"];
+ changed = true;
+ } else if (![version isEqualToString:solid]) {
+ [metadata setObject:solid forKey:@"LastVersion"];
+ last = now_;
+ [metadata setObject:last forKey:@"LastSeen"];
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ [Packages_ setObject:metadata forKey:key];
+ Changed_ = true;
+ }
+ _end
+
+ const char *section(iterator_.Section());
+ if (section == NULL)
+ section_ = nil;
+ else {
+ NSString *name([[NSString stringWithUTF8String:section] stringByReplacingCharacter:' ' withCharacter:'_']);
+
+ lookup:
+ if (NSDictionary *value = [SectionMap_ objectForKey:name])
+ if (NSString *rename = [value objectForKey:@"Rename"]) {
+ name = rename;
+ goto lookup;
+ }
+
+ section_ = [[name stringByReplacingCharacter:'_' withCharacter:' '] retain];
+ }
+
+ essential_ = (iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES;
+ } _end } return self;
+}
+
++ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database {