]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/tagfile.cc
Introduce tolower_ascii_unsafe() and use it for hashing
[apt.git] / apt-pkg / tagfile.cc
index 7a263c2b73158c2e66683987c331646ac3c9722f..200a7f2fdc7e6269974fb73b88d9804097a72d32 100644 (file)
 #include<config.h>
 
 #include <apt-pkg/tagfile.h>
+#include <apt-pkg/tagfile-keys.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/fileutl.h>
+#include <apt-pkg/string_view.h>
 
 #include <list>
 
@@ -30,6 +32,7 @@
                                                                        /*}}}*/
 
 using std::string;
+using APT::StringView;
 
 class APT_HIDDEN pkgTagFilePrivate                                     /*{{{*/
 {
@@ -96,7 +99,7 @@ public:
 };
                                                                        /*}}}*/
 
-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 */
@@ -108,7 +111,7 @@ 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;
 }
                                                                        /*}}}*/
 
@@ -298,7 +301,7 @@ static void RemoveCommentsFromBuffer(pkgTagFilePrivate * const d)
    std::vector<std::pair<char*, size_t>> good_parts;
    while (current <= d->End)
    {
-      size_t const restLength = (d->End - current) + 1;
+      size_t const restLength = (d->End - current);
       if (d->isCommentedLine == false)
       {
         current = static_cast<char*>(memchr(current, '#', restLength));
@@ -333,7 +336,7 @@ static void RemoveCommentsFromBuffer(pkgTagFilePrivate * const d)
         }
         ++current;
         // is the next line a comment, too?
-        if (current > d->End || *current != '#')
+        if (current >= d->End || *current != '#')
         {
            d->chunks.emplace_back(false, (current - bad_start));
            good_start = current;
@@ -472,6 +475,7 @@ pkgTagSection::pkgTagSection()
    : Section(0), d(new pkgTagSectionPrivate()), Stop(0)
 {
    memset(&AlphaIndexes, 0, sizeof(AlphaIndexes));
+   memset(&BetaIndexes, 0, sizeof(BetaIndexes));
 }
 APT_IGNORE_DEPRECATED_POP
                                                                        /*}}}*/
@@ -497,6 +501,7 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
       if (d->Tags.empty() == false)
       {
         memset(&AlphaIndexes, 0, sizeof(AlphaIndexes));
+        memset(&BetaIndexes, 0, sizeof(BetaIndexes));
         d->Tags.clear();
       }
       d->Tags.reserve(0x100);
@@ -508,7 +513,8 @@ 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);
@@ -524,11 +530,15 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
         // 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<size_t>(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);
         }
 
@@ -545,7 +555,9 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
            ;
         ++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 (; Stop < End && isspace_ascii(*Stop) != 0; ++Stop)
@@ -570,9 +582,13 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
       {
         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<size_t>(lastTagKey)] = TagCount;
+           } else {
+              if (BetaIndexes[lastTagHash] != 0)
+                 lastTagData.NextInBucket = BetaIndexes[lastTagHash];
+              APT_IGNORE_DEPRECATED(BetaIndexes[lastTagHash] = TagCount;)
+           }
            d->Tags.push_back(lastTagData);
         }
 
@@ -607,7 +623,7 @@ void pkgTagSection::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);
@@ -616,10 +632,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<size_t>(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;
 
@@ -639,13 +666,10 @@ 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;
@@ -655,25 +679,41 @@ bool pkgTagSection::Find(const char *Tag,const char *&Start,
    for (; isspace_ascii(End[-1]) != 0 && End > Start; --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;
@@ -682,17 +722,27 @@ string pkgTagSection::FindRawS(const char *Tag) const
 
    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
@@ -713,16 +763,28 @@ signed int pkgTagSection::FindI(const char *Tag,signed long Default) const
    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
@@ -737,31 +799,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)
 {
@@ -781,15 +881,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)
 {
@@ -839,13 +951,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_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());
 }
@@ -865,7 +977,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;
 
@@ -889,7 +1001,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;
       }
    }
@@ -919,7 +1031,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;
       }
    }
@@ -943,7 +1055,7 @@ 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;
@@ -1007,7 +1119,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;