X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/dfe66c72ffc010e019e96b35154e1ad4ab506a6e..9fa247dc9ba2aa28ae564e96cba5b2b23bcac91b:/apt-pkg/tagfile.cc diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 253b1b7a3..1aa67cc67 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -13,10 +13,15 @@ // Include Files /*{{{*/ #include +#include #include +#include #include #include #include +#include + +#include #include #include @@ -28,43 +33,46 @@ /*}}}*/ using std::string; +using APT::StringView; -class pkgTagFilePrivate +class APT_HIDDEN pkgTagFilePrivate /*{{{*/ { public: - void Reset(FileFd * const pFd, unsigned long long const pSize) + void Reset(FileFd * const pFd, pkgTagFile::Flags const pFlags) { - if (Buffer != NULL) - free(Buffer); + if (Map != NULL) + delete Map; + Map = NULL; Buffer = NULL; Fd = pFd; + Flags = pFlags; Start = NULL; End = NULL; Done = false; iOffset = 0; - Size = pSize; } - pkgTagFilePrivate(FileFd * const pFd, unsigned long long const Size) : Buffer(NULL) + pkgTagFilePrivate(FileFd * const pFd, pkgTagFile::Flags const pFlags) : Map(NULL) { - Reset(pFd, Size); + Reset(pFd, pFlags); } FileFd * Fd; + pkgTagFile::Flags Flags; char *Buffer; char *Start; char *End; bool Done; unsigned long long iOffset; - unsigned long long Size; + MMap *Map; ~pkgTagFilePrivate() { - if (Buffer != NULL) - free(Buffer); + if (Map != NULL) + delete Map; } }; - -class pkgTagSectionPrivate + /*}}}*/ +class APT_HIDDEN pkgTagSectionPrivate /*{{{*/ { public: pkgTagSectionPrivate() @@ -80,8 +88,9 @@ public: }; std::vector Tags; }; + /*}}}*/ -static unsigned long AlphaHash(const char *Text, size_t Length) /*{{{*/ +static unsigned long BetaHash(const char *Text, size_t Length) /*{{{*/ { /* This very simple hash function for the last 8 letters gives very good performance on the debian package files */ @@ -93,46 +102,46 @@ static unsigned long AlphaHash(const char *Text, size_t Length) /*{{{*/ unsigned long Res = 0; for (size_t i = 0; i < Length; ++i) Res = ((unsigned long)(Text[i]) & 0xDF) ^ (Res << 1); - return Res & 0xFF; + return Res & 0x7F; } /*}}}*/ // TagFile::pkgTagFile - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgTagFile::pkgTagFile(FileFd * const pFd,unsigned long long const Size) - : d(new pkgTagFilePrivate(pFd, Size + 4)) +pkgTagFile::pkgTagFile(FileFd * const pFd,pkgTagFile::Flags const pFlags) + : d(new pkgTagFilePrivate(pFd, pFlags)) { - Init(pFd, Size); + Init(pFd, pFlags); } -void pkgTagFile::Init(FileFd * const pFd,unsigned long long Size) +pkgTagFile::pkgTagFile(FileFd * const pFd) + : pkgTagFile(pFd, pkgTagFile::STRICT) { - /* The size is increased by 4 because if we start with the Size of the - filename we need to try to read 1 char more to see an EOF faster, 1 - char the end-pointer can be on and maybe 2 newlines need to be added - to the end of the file -> 4 extra chars */ - Size += 4; - d->Reset(pFd, Size); +} +void pkgTagFile::Init(FileFd * const pFd, pkgTagFile::Flags const pFlags) +{ + d->Reset(pFd, pFlags); - if (d->Fd->IsOpen() == false) - d->Start = d->End = d->Buffer = 0; - else - d->Buffer = (char*)malloc(sizeof(char) * Size); + if (d->Fd->IsOpen() == false || d->Fd->Size() == 0) + _error->Discard(); + else { + d->Map = new MMap(*d->Fd, MMap::ReadOnly); + d->Buffer = static_cast(d->Map->Data()); + } if (d->Buffer == NULL) d->Done = true; - else + else { d->Done = false; + d->End = d->Buffer + d->Map->Size(); + } - d->Start = d->End = d->Buffer; - d->iOffset = 0; - if (d->Done == false) - Fill(); + d->Start = d->Buffer; +} +void pkgTagFile::Init(FileFd * const pFd) +{ + Init(pFd, pkgTagFile::STRICT); } /*}}}*/ // TagFile::~pkgTagFile - Destructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ pkgTagFile::~pkgTagFile() { delete d; @@ -144,36 +153,6 @@ APT_PURE unsigned long pkgTagFile::Offset() return d->iOffset; } /*}}}*/ -// TagFile::Resize - Resize the internal buffer /*{{{*/ -// --------------------------------------------------------------------- -/* Resize the internal buffer (double it in size). Fail if a maximum size - * size is reached. - */ -bool pkgTagFile::Resize() -{ - // fail is the buffer grows too big - if(d->Size > 1024*1024+1) - return false; - - return Resize(d->Size * 2); -} -bool pkgTagFile::Resize(unsigned long long const newSize) -{ - unsigned long long const EndSize = d->End - d->Start; - - // get new buffer and use it - char* newBuffer = (char*)realloc(d->Buffer, sizeof(char) * newSize); - if (newBuffer == NULL) - return false; - d->Buffer = newBuffer; - d->Size = newSize; - - // update the start/end pointers to the new buffer - d->Start = d->Buffer; - d->End = d->Start + EndSize; - return true; -} - /*}}}*/ // TagFile::Step - Advance to the next section /*{{{*/ // --------------------------------------------------------------------- /* If the Section Scanner fails we refill the buffer and try again. @@ -182,77 +161,18 @@ bool pkgTagFile::Resize(unsigned long long const newSize) */ bool pkgTagFile::Step(pkgTagSection &Tag) { - if(Tag.Scan(d->Start,d->End - d->Start) == false) + if(Tag.Scan(d->Start,d->End - d->Start,(d->Flags & SUPPORT_COMMENTS) != 0) == false) { - do - { - if (Fill() == false) - return false; - - if(Tag.Scan(d->Start,d->End - d->Start, false)) - break; - - if (Resize() == false) - return _error->Error(_("Unable to parse package file %s (%d)"), + if (d->Start == d->End) + return false; + else + return _error->Warning(_("Unable to parse package file %s (%d)"), d->Fd->Name().c_str(), 1); - - } while (Tag.Scan(d->Start,d->End - d->Start, false) == false); } - d->Start += Tag.size(); - d->iOffset += Tag.size(); - - Tag.Trim(); - return true; -} - /*}}}*/ -// TagFile::Fill - Top up the buffer /*{{{*/ -// --------------------------------------------------------------------- -/* This takes the bit at the end of the buffer and puts it at the start - then fills the rest from the file */ -bool pkgTagFile::Fill() -{ - unsigned long long EndSize = d->End - d->Start; - unsigned long long Actual = 0; - - memmove(d->Buffer,d->Start,EndSize); - d->Start = d->Buffer; - d->End = d->Buffer + EndSize; - - if (d->Done == false) - { - // See if only a bit of the file is left - unsigned long long const dataSize = d->Size - ((d->End - d->Buffer) + 1); - if (d->Fd->Read(d->End, dataSize, &Actual) == false) - return false; - if (Actual != dataSize) - d->Done = true; - d->End += Actual; - } - - if (d->Done == true) - { - if (EndSize <= 3 && Actual == 0) - return false; - if (d->Size - (d->End - d->Buffer) < 4) - return true; - - // Append a double new line if one does not exist - unsigned int LineCount = 0; - for (const char *E = d->End - 1; E - d->End < 6 && (*E == '\n' || *E == '\r'); E--) - if (*E == '\n') - LineCount++; - if (LineCount < 2) - { - if ((unsigned)(d->End - d->Buffer) >= d->Size) - Resize(d->Size + 3); - for (; LineCount < 2; LineCount++) - *d->End++ = '\n'; - } - - return true; - } - + size_t tagSize = Tag.size(); + d->Start += tagSize; + d->iOffset += tagSize; return true; } /*}}}*/ @@ -262,40 +182,16 @@ bool pkgTagFile::Fill() that is there */ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset) { - // We are within a buffer space of the next hit.. - if (Offset >= d->iOffset && d->iOffset + (d->End - d->Start) > Offset) - { - unsigned long long Dist = Offset - d->iOffset; - d->Start += Dist; - d->iOffset += Dist; - // if we have seen the end, don't ask for more - if (d->Done == true) - return Tag.Scan(d->Start, d->End - d->Start); - else - return Step(Tag); - } + unsigned int Size(d->Map->Size()); + if (Offset >= Size) + return false; // Reposition and reload.. d->iOffset = Offset; d->Done = false; - if (d->Fd->Seek(Offset) == false) - return false; - d->End = d->Start = d->Buffer; - - if (Fill() == false) - return false; + d->Start = d->Buffer + d->iOffset; - if (Tag.Scan(d->Start, d->End - d->Start) == true) - return true; - - // This appends a double new line (for the real eof handling) - if (Fill() == false) - return false; - - if (Tag.Scan(d->Start, d->End - d->Start, false) == false) - return _error->Error(_("Unable to parse package file %s (%d)"),d->Fd->Name().c_str(), 2); - - return true; + return Step(Tag); } /*}}}*/ // pkgTagSection::pkgTagSection - Constructor /*{{{*/ @@ -306,35 +202,25 @@ pkgTagSection::pkgTagSection() : Section(0), d(new pkgTagSectionPrivate()), Stop(0) { memset(&AlphaIndexes, 0, sizeof(AlphaIndexes)); + memset(&BetaIndexes, 0, sizeof(BetaIndexes)); } APT_IGNORE_DEPRECATED_POP /*}}}*/ // TagSection::Scan - Scan for the end of the header information /*{{{*/ -bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const Restart) +bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength,bool const SupportComments) { Section = Start; const char *End = Start + MaxLength; - if (Restart == false && d->Tags.empty() == false) - { - Stop = Section + d->Tags.back().StartTag; - if (End <= Stop) - return false; - Stop = (const char *)memchr(Stop,'\n',End - Stop); - if (Stop == NULL) - return false; - ++Stop; - } - else + Stop = Section; + if (d->Tags.empty() == false) { - Stop = Section; - if (d->Tags.empty() == false) - { - memset(&AlphaIndexes, 0, sizeof(AlphaIndexes)); - d->Tags.clear(); - } - d->Tags.reserve(0x100); + memset(&AlphaIndexes, 0, sizeof(AlphaIndexes)); + memset(&BetaIndexes, 0, sizeof(BetaIndexes)); + d->Tags.clear(); } + d->Tags.reserve(0x100); + unsigned int TagCount = d->Tags.size(); if (Stop == 0) @@ -342,27 +228,32 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R pkgTagSectionPrivate::TagData lastTagData(0); lastTagData.EndTag = 0; - unsigned long lastTagHash = 0; + Key lastTagKey = Key::Unknown; + unsigned int lastTagHash = 0; while (Stop < End) { - TrimRecord(true,End); + TrimRecord(true,End,SupportComments); // this can happen when TrimRecord trims away the entire Record // (e.g. because it just contains comments) if(Stop == End) - return true; + goto end; // Start a new index and add it to the hash - if (isspace(Stop[0]) == 0) + if (isspace_ascii(Stop[0]) == 0) { // store the last found tag if (lastTagData.EndTag != 0) { - if (AlphaIndexes[lastTagHash] != 0) - lastTagData.NextInBucket = AlphaIndexes[lastTagHash]; - APT_IGNORE_DEPRECATED_PUSH - AlphaIndexes[lastTagHash] = TagCount; - APT_IGNORE_DEPRECATED_POP + if (lastTagKey != Key::Unknown) { + AlphaIndexes[static_cast(lastTagKey)] = TagCount; + } else { + if (BetaIndexes[lastTagHash] != 0) + lastTagData.NextInBucket = BetaIndexes[lastTagHash]; + APT_IGNORE_DEPRECATED_PUSH + BetaIndexes[lastTagHash] = TagCount; + APT_IGNORE_DEPRECATED_POP + } d->Tags.push_back(lastTagData); } @@ -375,23 +266,27 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R // find the end of the tag (which might or might not be the colon) char const * EndTag = Colon; --EndTag; - for (; EndTag > Stop && isspace(*EndTag) != 0; --EndTag) + for (; EndTag > Stop && isspace_ascii(*EndTag) != 0; --EndTag) ; ++EndTag; lastTagData.EndTag = EndTag - Section; - lastTagHash = AlphaHash(Stop, EndTag - Stop); + lastTagKey = pkgTagHash(Stop, EndTag - Stop); + if (lastTagKey == Key::Unknown) + lastTagHash = BetaHash(Stop, EndTag - Stop); // find the beginning of the value Stop = Colon + 1; - for (; isspace(*Stop) != 0; ++Stop); - if (Stop >= End) - return false; + for (; Stop < End && isspace_ascii(*Stop) != 0; ++Stop) + if (*Stop == '\n' && (Stop+1 == End || Stop[1] != ' ')) + break; lastTagData.StartValue = Stop - Section; } Stop = (const char *)memchr(Stop,'\n',End - Stop); - if (Stop == 0) - return false; + if (Stop == 0) { + Stop = End; + goto end; + } for (; Stop+1 < End && Stop[1] == '\r'; Stop++) /* nothing */ @@ -399,47 +294,49 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R // Double newline marks the end of the record if (Stop+1 < End && Stop[1] == '\n') - { + end: { if (lastTagData.EndTag != 0) { - if (AlphaIndexes[lastTagHash] != 0) - lastTagData.NextInBucket = AlphaIndexes[lastTagHash]; - APT_IGNORE_DEPRECATED(AlphaIndexes[lastTagHash] = TagCount;) + if (lastTagKey != Key::Unknown) { + AlphaIndexes[static_cast(lastTagKey)] = TagCount; + } else { + if (BetaIndexes[lastTagHash] != 0) + lastTagData.NextInBucket = BetaIndexes[lastTagHash]; + APT_IGNORE_DEPRECATED(BetaIndexes[lastTagHash] = TagCount;) + } d->Tags.push_back(lastTagData); } + if (d->Tags.empty()) + return false; + pkgTagSectionPrivate::TagData const td(Stop - Section); d->Tags.push_back(td); - TrimRecord(false,End); + TrimRecord(false,End,SupportComments); return true; } Stop++; } - return false; + goto end; } /*}}}*/ // TagSection::TrimRecord - Trim off any garbage before/after a record /*{{{*/ // --------------------------------------------------------------------- /* There should be exactly 2 newline at the end of the record, no more. */ -void pkgTagSection::TrimRecord(bool BeforeRecord, const char*& End) -{ - if (BeforeRecord == true) - return; - for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r'); Stop++); -} - /*}}}*/ -// TagSection::Trim - Trim off any trailing garbage /*{{{*/ -// --------------------------------------------------------------------- -/* There should be exactly 1 newline at the end of the buffer, no more. */ -void pkgTagSection::Trim() -{ - for (; Stop > Section + 2 && (Stop[-2] == '\n' || Stop[-2] == '\r'); Stop--); +void pkgTagSection::TrimRecord(bool BeforeRecord, const char*& End, bool SupportComments) +{ trim: + if (BeforeRecord == false) + for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r'); Stop++); + if (SupportComments && Stop < End && Stop[0] == '#') { + Stop = (const char*) memchr(Stop,'\n',End-Stop) ?: End; + goto trim; + } } /*}}}*/ // TagSection::Exists - return True if a tag exists /*{{{*/ -bool pkgTagSection::Exists(const char* const Tag) const +bool pkgTagSection::Exists(StringView Tag) const { unsigned int tmp; return Find(Tag, tmp); @@ -448,10 +345,21 @@ bool pkgTagSection::Exists(const char* const Tag) const // TagSection::Find - Locate a tag /*{{{*/ // --------------------------------------------------------------------- /* This searches the section for a tag that matches the given string. */ -bool pkgTagSection::Find(const char *Tag,unsigned int &Pos) const +bool pkgTagSection::Find(Key key,unsigned int &Pos) const { - size_t const Length = strlen(Tag); - unsigned int Bucket = AlphaIndexes[AlphaHash(Tag, Length)]; + auto Bucket = AlphaIndexes[static_cast(key)]; + Pos = Bucket - 1; + return Bucket != 0; +} +bool pkgTagSection::Find(StringView TagView,unsigned int &Pos) const +{ + const char * const Tag = TagView.data(); + size_t const Length = TagView.length(); + auto key = pkgTagHash(Tag, Length); + if (key != Key::Unknown) + return Find(key, Pos); + + unsigned int Bucket = BetaIndexes[BetaHash(Tag, Length)]; if (Bucket == 0) return false; @@ -471,60 +379,83 @@ bool pkgTagSection::Find(const char *Tag,unsigned int &Pos) const Pos = 0; return false; } -bool pkgTagSection::Find(const char *Tag,const char *&Start, + +bool pkgTagSection::FindInternal(unsigned int Pos, const char *&Start, const char *&End) const { - unsigned int Pos; - if (Find(Tag, Pos) == false) - return false; - Start = Section + d->Tags[Pos].StartValue; // Strip off the gunk from the end End = Section + d->Tags[Pos + 1].StartTag; if (unlikely(Start > End)) return _error->Error("Internal parsing error"); - for (; isspace(End[-1]) != 0 && End > Start; --End); + for (; End > Start && isspace_ascii(End[-1]) != 0; --End); return true; +} +bool pkgTagSection::Find(StringView Tag,const char *&Start, + const char *&End) const +{ + unsigned int Pos; + return Find(Tag, Pos) && FindInternal(Pos, Start, End); +} +bool pkgTagSection::Find(Key key,const char *&Start, + const char *&End) const +{ + unsigned int Pos; + return Find(key, Pos) && FindInternal(Pos, Start, End); } /*}}}*/ // TagSection::FindS - Find a string /*{{{*/ -string pkgTagSection::FindS(const char *Tag) const +StringView pkgTagSection::Find(StringView Tag) const { const char *Start; const char *End; if (Find(Tag,Start,End) == false) - return string(); - return string(Start,End); + return StringView(); + return StringView(Start, End - Start); +} +StringView pkgTagSection::Find(Key key) const +{ + const char *Start; + const char *End; + if (Find(key,Start,End) == false) + return StringView(); + return StringView(Start, End - Start); } /*}}}*/ // TagSection::FindRawS - Find a string /*{{{*/ -string pkgTagSection::FindRawS(const char *Tag) const +StringView pkgTagSection::FindRawInternal(unsigned int Pos) const { - unsigned int Pos; - if (Find(Tag, Pos) == false) - return ""; - char const *Start = (char const *) memchr(Section + d->Tags[Pos].EndTag, ':', d->Tags[Pos].StartValue - d->Tags[Pos].EndTag); ++Start; char const *End = Section + d->Tags[Pos + 1].StartTag; if (unlikely(Start > End)) return ""; - for (; isspace(End[-1]) != 0 && End > Start; --End); + for (; isspace_ascii(End[-1]) != 0 && End > Start; --End); - return std::string(Start, End - Start); + return StringView(Start, End - Start); +} +StringView pkgTagSection::FindRaw(StringView Tag) const +{ + unsigned int Pos; + return Find(Tag, Pos) ? FindRawInternal(Pos) : ""; +} +StringView pkgTagSection::FindRaw(Key key) const +{ + unsigned int Pos; + return Find(key, Pos) ? FindRawInternal(Pos) : ""; } /*}}}*/ // TagSection::FindI - Find an integer /*{{{*/ // --------------------------------------------------------------------- /* */ -signed int pkgTagSection::FindI(const char *Tag,signed long Default) const +signed int pkgTagSection::FindIInternal(unsigned int Pos,signed long Default) const { const char *Start; const char *Stop; - if (Find(Tag,Start,Stop) == false) + if (FindInternal(Pos,Start,Stop) == false) return Default; // Copy it into a temp buffer so we can use strtol @@ -533,22 +464,40 @@ signed int pkgTagSection::FindI(const char *Tag,signed long Default) const return Default; strncpy(S,Start,Stop-Start); S[Stop - Start] = 0; - + + errno = 0; char *End; signed long Result = strtol(S,&End,10); + if (errno == ERANGE || + Result < std::numeric_limits::min() || Result > std::numeric_limits::max()) { + errno = ERANGE; + _error->Error(_("Cannot convert %s to integer: out of range"), S); + } if (S == End) return Default; return Result; +} +signed int pkgTagSection::FindI(Key key,signed long Default) const +{ + unsigned int Pos; + + return Find(key, Pos) ? FindIInternal(Pos) : Default; +} +signed int pkgTagSection::FindI(StringView Tag,signed long Default) const +{ + unsigned int Pos; + + return Find(Tag, Pos) ? FindIInternal(Pos, Default) : Default; } /*}}}*/ // TagSection::FindULL - Find an unsigned long long integer /*{{{*/ // --------------------------------------------------------------------- /* */ -unsigned long long pkgTagSection::FindULL(const char *Tag, unsigned long long const &Default) const +unsigned long long pkgTagSection::FindULLInternal(unsigned int Pos, unsigned long long const &Default) const { const char *Start; const char *Stop; - if (Find(Tag,Start,Stop) == false) + if (FindInternal(Pos,Start,Stop) == false) return Default; // Copy it into a temp buffer so we can use strtoull @@ -563,31 +512,69 @@ unsigned long long pkgTagSection::FindULL(const char *Tag, unsigned long long co if (S == End) return Default; return Result; +} +unsigned long long pkgTagSection::FindULL(Key key, unsigned long long const &Default) const +{ + unsigned int Pos; + + return Find(key, Pos) ? FindULLInternal(Pos, Default) : Default; +} +unsigned long long pkgTagSection::FindULL(StringView Tag, unsigned long long const &Default) const +{ + unsigned int Pos; + + return Find(Tag, Pos) ? FindULLInternal(Pos, Default) : Default; } /*}}}*/ // TagSection::FindB - Find boolean value /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgTagSection::FindB(const char *Tag, bool const &Default) const +bool pkgTagSection::FindBInternal(unsigned int Pos, bool Default) const { const char *Start, *Stop; - if (Find(Tag, Start, Stop) == false) + if (FindInternal(Pos, Start, Stop) == false) return Default; return StringToBool(string(Start, Stop)); +} +bool pkgTagSection::FindB(Key key, bool Default) const +{ + unsigned int Pos; + return Find(key, Pos) ? FindBInternal(Pos, Default): Default; +} +bool pkgTagSection::FindB(StringView Tag, bool Default) const +{ + unsigned int Pos; + return Find(Tag, Pos) ? FindBInternal(Pos, Default) : Default; } /*}}}*/ // TagSection::FindFlag - Locate a yes/no type flag /*{{{*/ // --------------------------------------------------------------------- /* The bits marked in Flag are masked on/off in Flags */ -bool pkgTagSection::FindFlag(const char * const Tag, uint8_t &Flags, +bool pkgTagSection::FindFlagInternal(unsigned int Pos, uint8_t &Flags, uint8_t const Flag) const { const char *Start; const char *Stop; - if (Find(Tag,Start,Stop) == false) + if (FindInternal(Pos,Start,Stop) == false) return true; return FindFlag(Flags, Flag, Start, Stop); } +bool pkgTagSection::FindFlag(Key key, uint8_t &Flags, + uint8_t const Flag) const +{ + unsigned int Pos; + if (Find(key,Pos) == false) + return true; + return FindFlagInternal(Pos, Flags, Flag); +} +bool pkgTagSection::FindFlag(StringView Tag, uint8_t &Flags, + uint8_t const Flag) const +{ + unsigned int Pos; + if (Find(Tag,Pos) == false) + return true; + return FindFlagInternal(Pos, Flags, Flag); +} bool pkgTagSection::FindFlag(uint8_t &Flags, uint8_t const Flag, char const* const Start, char const* const Stop) { @@ -607,15 +594,27 @@ bool pkgTagSection::FindFlag(uint8_t &Flags, uint8_t const Flag, } return true; } -bool pkgTagSection::FindFlag(const char *Tag,unsigned long &Flags, +bool pkgTagSection::FindFlagInternal(unsigned int Pos,unsigned long &Flags, unsigned long Flag) const { const char *Start; const char *Stop; - if (Find(Tag,Start,Stop) == false) + if (FindInternal(Pos,Start,Stop) == false) return true; return FindFlag(Flags, Flag, Start, Stop); } +bool pkgTagSection::FindFlag(Key key,unsigned long &Flags, + unsigned long Flag) const +{ + unsigned int Pos; + return Find(key, Pos) ? FindFlagInternal(Pos, Flags, Flag) : true; +} +bool pkgTagSection::FindFlag(StringView Tag,unsigned long &Flags, + unsigned long Flag) const +{ + unsigned int Pos; + return Find(Tag, Pos) ? FindFlagInternal(Pos, Flags, Flag) : true; +} bool pkgTagSection::FindFlag(unsigned long &Flags, unsigned long Flag, char const* Start, char const* Stop) { @@ -636,11 +635,12 @@ bool pkgTagSection::FindFlag(unsigned long &Flags, unsigned long Flag, return true; } /*}}}*/ -void pkgTagSection::Get(const char *&Start,const char *&Stop,unsigned int I) const +void pkgTagSection::Get(const char *&Start,const char *&Stop,unsigned int I) const/*{{{*/ { Start = Section + d->Tags[I].StartTag; Stop = Section + d->Tags[I+1].StartTag; } + /*}}}*/ APT_PURE unsigned int pkgTagSection::Count() const { /*{{{*/ if (d->Tags.empty() == true) return 0; @@ -664,13 +664,13 @@ pkgTagSection::Tag pkgTagSection::Tag::Rewrite(std::string const &Name, std::str else return Tag(REWRITE, Name, Data); } -static bool WriteTag(FileFd &File, std::string Tag, std::string const &Value) +static bool WriteTag(FileFd &File, std::string Tag, StringView Value) { - if (Value.empty() || isspace(Value[0]) != 0) + if (Value.empty() || isspace_ascii(Value[0]) != 0) Tag.append(":"); else Tag.append(": "); - Tag.append(Value); + Tag.append(Value.data(), Value.length()); Tag.append("\n"); return File.Write(Tag.c_str(), Tag.length()); } @@ -690,7 +690,7 @@ static bool RewriteTags(FileFd &File, pkgTagSection const * const This, char con } else if(R->Action == pkgTagSection::Tag::RENAME && R->Data.length() == TagLen && strncasecmp(R->Data.c_str(), Tag, R->Data.length()) == 0) - data = This->FindRawS(R->Name.c_str()); + data = This->FindRaw(R->Name.c_str()).to_string(); else continue; @@ -714,7 +714,7 @@ bool pkgTagSection::Write(FileFd &File, char const * const * const Order, std::v if (Exists(Order[I]) == false) continue; - if (WriteTag(File, Order[I], FindRawS(Order[I])) == false) + if (WriteTag(File, Order[I], FindRaw(Order[I])) == false) return false; } } @@ -744,7 +744,7 @@ bool pkgTagSection::Write(FileFd &File, char const * const * const Order, std::v if (R != Rewrite.end()) continue; - if (WriteTag(File, name, FindRawS(name.c_str())) == false) + if (WriteTag(File, name, FindRaw(name)) == false) return false; } } @@ -768,21 +768,13 @@ bool pkgTagSection::Write(FileFd &File, char const * const * const Order, std::v continue; } - if (WriteTag(File, name, ((R->Action == Tag::RENAME) ? FindRawS(R->Name.c_str()) : R->Data)) == false) + if (WriteTag(File, name, ((R->Action == Tag::RENAME) ? FindRaw(R->Name) : R->Data)) == false) return false; } return true; } /*}}}*/ -void pkgUserTagSection::TrimRecord(bool /*BeforeRecord*/, const char* &End)/*{{{*/ -{ - for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r' || Stop[0] == '#'); Stop++) - if (Stop[0] == '#') - Stop = (const char*) memchr(Stop,'\n',End-Stop); -} - /*}}}*/ - #include "tagfile-order.c" // TFRewrite - Rewrite a control record /*{{{*/ @@ -820,7 +812,7 @@ bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[], Visited[J] |= 2; if (Rewrite[J].Rewrite != 0 && Rewrite[J].Rewrite[0] != 0) { - if (isspace(Rewrite[J].Rewrite[0])) + if (isspace_ascii(Rewrite[J].Rewrite[0])) fprintf(Output,"%s:%s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite); else fprintf(Output,"%s: %s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite); @@ -832,7 +824,7 @@ bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[], // See if it is in the fragment unsigned Pos; - if (Tags.Find(Order[I],Pos) == false) + if (Tags.Find(StringView(Order[I]),Pos) == false) continue; Visited[Pos] |= 1; @@ -876,7 +868,7 @@ bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[], Visited[J] |= 2; if (Rewrite[J].Rewrite != 0 && Rewrite[J].Rewrite[0] != 0) { - if (isspace(Rewrite[J].Rewrite[0])) + if (isspace_ascii(Rewrite[J].Rewrite[0])) fprintf(Output,"%s:%s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite); else fprintf(Output,"%s: %s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite); @@ -905,7 +897,7 @@ bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[], if (Rewrite[J].Rewrite != 0 && Rewrite[J].Rewrite[0] != 0) { - if (isspace(Rewrite[J].Rewrite[0])) + if (isspace_ascii(Rewrite[J].Rewrite[0])) fprintf(Output,"%s:%s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite); else fprintf(Output,"%s: %s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite);