X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/9c14e3d619e713aefa623986b5bbae81a1d6cc94..cf544e1458bbe2a245ce0275f3b69061604ecf2e:/apt-pkg/tagfile.cc diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index aaef3da8b..bdfa302d8 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -1,23 +1,23 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: tagfile.cc,v 1.6 1998/07/09 05:12:32 jgg Exp $ +// $Id: tagfile.cc,v 1.21 1999/01/31 07:01:11 jgg Exp $ /* ###################################################################### Fast scanner for RFC-822 type header information - This uses a rotating 64K buffer to load the package information into. + This uses a rotating buffer to load the package information into. The scanner runs over it and isolates and indexes a single section. ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ #ifdef __GNUG__ -#pragma implementation "pkglib/tagfile.h" +#pragma implementation "apt-pkg/tagfile.h" #endif -#include -#include -#include +#include +#include +#include #include #include @@ -26,10 +26,10 @@ // TagFile::pkgTagFile - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgTagFile::pkgTagFile(File &Fd) : Fd(Fd) +pkgTagFile::pkgTagFile(FileFd &Fd,unsigned long Size) : Fd(Fd), Size(Size) { - Buffer = new char[64*1024]; - Start = End = Buffer + 64*1024; + Buffer = new char[Size]; + Start = End = Buffer; Left = Fd.Size(); iOffset = 0; Fill(); @@ -46,7 +46,7 @@ bool pkgTagFile::Step(pkgTagSection &Tag) return false; if (Tag.Scan(Start,End - Start) == false) - return _error->Error("Unable to parse package file"); + return _error->Error("Unable to parse package file %s",Fd.Name().c_str()); } Start += Tag.size(); iOffset += Tag.size(); @@ -60,67 +60,114 @@ bool pkgTagFile::Step(pkgTagSection &Tag) then fills the rest from the file */ bool pkgTagFile::Fill() { - unsigned long Size = End - Start; + unsigned long EndSize = End - Start; + + memmove(Buffer,Start,EndSize); + Start = Buffer; + End = Buffer + EndSize; if (Left == 0) { - if (Size <= 1) + if (EndSize <= 3) return false; + if (Size - (End - Buffer) < 4) + return true; + + // Append a double new line if one does not exist + unsigned int LineCount = 0; + for (const char *E = End - 1; E - End < 6 && (*E == '\n' || *E == '\r'); E--) + if (*E == '\n') + LineCount++; + for (; LineCount < 2; LineCount++) + *End++ = '\n'; + return true; } - memmove(Buffer,Start,Size); - Start = Buffer; - - // See if only a bit of the file is left or if - if (Left < End - Buffer - Size) + // See if only a bit of the file is left + if (Left < Size - (End - Buffer)) { - if (Fd.Read(Buffer + Size,Left) == false) + if (Fd.Read(End,Left) == false) return false; - End = Buffer + Size + Left; + + End += Left; Left = 0; } else { - if (Fd.Read(Buffer + Size, End - Buffer - Size) == false) + if (Fd.Read(End,Size - (End - Buffer)) == false) return false; - Left -= End - Buffer - Size; + + Left -= Size - (End - Buffer); + End = Buffer + Size; } return true; } /*}}}*/ +// TagFile::Jump - Jump to a pre-recorded location in the file /*{{{*/ +// --------------------------------------------------------------------- +/* This jumps to a pre-recorded file location and reads the record + that is there */ +bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long Offset) +{ + iOffset = Offset; + Left = Fd.Size() - Offset; + if (Fd.Seek(Offset) == false) + return false; + End = Start = Buffer; + + if (Fill() == false) + return false; + + if (Tag.Scan(Start,End - Start) == false) + return _error->Error("Unable to parse package file"); + return true; +} + /*}}}*/ // TagSection::Scan - Scan for the end of the header information /*{{{*/ // --------------------------------------------------------------------- /* This looks for the first double new line in the data stream. It also - indexes the tags in the section. */ + indexes the tags in the section. This very simple hash function for the + first 3 letters gives very good performance on the debian package files */ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength) { const char *End = Start + MaxLength; Stop = Section = Start; + memset(AlphaIndexes,0,sizeof(AlphaIndexes)); + + if (Stop == 0) + return false; TagCount = 0; - Indexes[TagCount++] = Stop - Section; - Stop++; - for (; Stop < End; Stop++) + while (TagCount < sizeof(Indexes)/sizeof(Indexes[0])) { - if (Stop[-1] != '\n') - continue; - if (Stop[0] == '\n') + // Start a new index and add it to the hash + if (isspace(Stop[0]) == 0) + { + Indexes[TagCount++] = Stop - Section; + unsigned char A = tolower(Stop[0]) - 'a'; + unsigned char B = tolower(Stop[1]) - 'a'; + unsigned char C = tolower(Stop[3]) - 'a'; + AlphaIndexes[((A + C/3)%26) + 26*((B + C/2)%26)] = TagCount; + } + + Stop = (const char *)memchr(Stop,'\n',End - Stop); + + if (Stop == 0) + return false; + for (; Stop[1] == '\r' && Stop+1 < End; Stop++); + + // Double newline or end of file marks the end of the record + if (Stop+1 >= End || Stop[1] == '\n') { - // Extra one at the end to simplify find Indexes[TagCount] = Stop - Section; - for (; Stop[0] == '\n' && Stop < End; Stop++); + for (; (Stop[0] == '\n' || Stop[0] == '\r') && Stop < End; Stop++); return true; - break; } - if (isspace(Stop[0]) == 0) - Indexes[TagCount++] = Stop - Section; - - // Just in case. - if (TagCount > sizeof(Indexes)/sizeof(Indexes[0])) - TagCount = sizeof(Indexes)/sizeof(Indexes[0]); - } + Stop++; + } + return false; } /*}}}*/ @@ -131,13 +178,24 @@ bool pkgTagSection::Find(const char *Tag,const char *&Start, const char *&End) { unsigned int Length = strlen(Tag); - for (unsigned int I = 0; I != TagCount; I++) + unsigned char A = tolower(Tag[0]) - 'a'; + unsigned char B = tolower(Tag[1]) - 'a'; + unsigned char C = tolower(Tag[3]) - 'a'; + unsigned int I = AlphaIndexes[((A + C/3)%26) + 26*((B + C/2)%26)]; + if (I == 0) + return false; + I--; + + for (unsigned int Counter = 0; Counter != TagCount; Counter++, + I = (I+1)%TagCount) { - if (strncasecmp(Tag,Section + Indexes[I],Length) != 0) + const char *St; + St = Section + Indexes[I]; + if (strncasecmp(Tag,St,Length) != 0) continue; // Make sure the colon is in the right place - const char *C = Section + Length + Indexes[I]; + const char *C = St + Length; for (; isspace(*C) != 0; C++); if (*C != ':') continue; @@ -147,96 +205,77 @@ bool pkgTagSection::Find(const char *Tag,const char *&Start, End = Section + Indexes[I+1]; for (; (isspace(*Start) != 0 || *Start == ':') && Start < End; Start++); for (; isspace(End[-1]) != 0 && End > Start; End--); + return true; } + Start = End = 0; return false; } /*}}}*/ +// TagSection::FindS - Find a string /*{{{*/ +// --------------------------------------------------------------------- +/* */ +string pkgTagSection::FindS(const char *Tag) +{ + const char *Start; + const char *End; + if (Find(Tag,Start,End) == false) + return string(); + return string(Start,End); +} + /*}}}*/ +// TagSection::FindI - Find an integer /*{{{*/ +// --------------------------------------------------------------------- +/* */ +signed int pkgTagSection::FindI(const char *Tag,signed long Default) +{ + const char *Start; + const char *Stop; + if (Find(Tag,Start,Stop) == false) + return Default; -#include -#include - -int main(int argc,char *argv[]) + // Copy it into a temp buffer so we can use strtol + char S[300]; + if ((unsigned)(Stop - Start) >= sizeof(S)) + return Default; + strncpy(S,Start,Stop-Start); + S[Stop - Start] = 0; + + char *End; + signed long Result = strtol(S,&End,10); + if (S == End) + return Default; + return Result; +} + /*}}}*/ +// TagSection::FindFlag - Locate a yes/no type flag /*{{{*/ +// --------------------------------------------------------------------- +/* The bits marked in Flag are masked on/off in Flags */ +bool pkgTagSection::FindFlag(const char *Tag,unsigned long &Flags, + unsigned long Flag) { - pkglibInitialize(*_config); - cout << _config->Find("APT::arch") << endl; - cout << _config->FindDir("DIR::Etc::sourcelist") << endl; + const char *Start; + const char *Stop; + if (Find(Tag,Start,Stop) == false) + return true; - { - File CacheF("./cache",File::WriteEmpty); - DynamicMMap Map(CacheF,MMap::Public); - pkgCacheGenerator Gen(Map); + switch (StringToBool(string(Start,Stop))) + { + case 0: + Flags &= ~Flag; + return true; - for (int I = 1; I != argc; I++) - { - cout << "Merging in " << argv[I] << endl; - File F(argv[I],File::ReadOnly); - Gen.SelectFile(argv[I]); - debListParser Parser(F); - Gen.MergeList(Parser); - } - } -/* - { - File CacheF("./cache",File::WriteExists); - MMap Map(CacheF,MMap::Public | MMap::ReadOnly); - pkgCache Cache(Map); - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) - { - cout << "Package: " << I.Name() << endl; - for (pkgCache::VerIterator V = I.VersionList(); V.end() == false; V++) - { - cout << "Version: " << V.VerStr() << endl; - cout << "Size: " << V->Size << endl; - cout << "Installed-Size: " << V->InstalledSize << endl; - cout << "Section: " << V.Section() << endl; - cout << "Priority: " << Cache.Priority(V->Priority) << endl; - - pkgCache::PrvIterator P = V.ProvidesList(); - if (P.end() == false) - { - cout << "Provides: "; - for (; P.end() == false; P++) - cout << P.Name() << ", "; - cout << endl; - } - } - cout << endl; - } - } -*/ -#if 0 - pkgTagSection I; - while (Test.Step(I) == true) - { - const char *Start; - const char *End; - if (I.Find("Package",Start,End) == false) - { - cout << "Failed" << endl; - continue; - } - - cout << "Package: " << string(Start,End - Start) << endl; - -/* for (const char *I = Start; I < End; I++) - { - const char *Begin = I; - bool Number = true; - while (isspace(*I) == 0 && ispunct(*I) == 0 && I < End) - { - if (isalpha(*I) != 0) - Number = false; - I++; - } - if (Number == false) - cout << string(Begin,I-Begin) << endl; - while ((isspace(*I) != 0 || ispunct(*I) != 0) && I < End) - I++; - I--; - } */ + case 1: + Flags |= Flag; + return true; + + default: + _error->Warning("Unknown flag value"); + return true; } -#endif - _error->DumpErrors(); + return true; } + /*}}}*/ + +