Browse Source

Switch performance critical code to use APT::StringView

This improves performance of the cache generation on my
ARM platform (4x Cortex A15) by about 10% to 20% from
2.35-2.50 to 2.1 seconds.
Julian Andres Klode 8 years ago
parent
commit
eff0c22e59

+ 7 - 0
apt-pkg/cacheiterators.h

@@ -35,6 +35,9 @@
 #include<iterator>
 #include <iosfwd>
 #include <string>
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+#include <apt-pkg/string_view.h>
+#endif
 
 #include<string.h>
 
@@ -114,6 +117,10 @@ class pkgCache::GrpIterator: public Iterator<Group, GrpIterator> {
 	inline const char *Name() const {return S->Name == 0?0:Owner->StrP + S->Name;}
 	inline PkgIterator PackageList() const;
 	PkgIterator FindPkg(std::string Arch = "any") const;
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+	APT_HIDDEN PkgIterator FindPkg(APT::StringView Arch = APT::StringView("any", 3)) const;
+	APT_HIDDEN PkgIterator FindPkg(const char *Arch) const;
+#endif
 	/** \brief find the package with the "best" architecture
 
 	    The best architecture is either the "native" or the first

+ 25 - 1
apt-pkg/contrib/hashsum_template.h

@@ -13,6 +13,9 @@
 
 #include <string>
 #include <cstring>
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+#include <apt-pkg/string_view.h>
+#endif
 
 #include <apt-pkg/strutl.h>
 
@@ -80,7 +83,16 @@ class HashSumValue
    {
       return Hex2Num(Str,Sum,sizeof(Sum));
    }
-
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+   APT_HIDDEN bool Set(APT::StringView Str)
+   {
+      return Hex2Num(Str,Sum,sizeof(Sum));
+   }
+   APT_HIDDEN bool Set(const char *Str)
+   {
+      return Hex2Num(APT::StringView(Str),Sum,sizeof(Sum));
+   }
+#endif
    inline void Set(unsigned char S[N/8])
    {
       for (int I = 0; I != sizeof(Sum); ++I)
@@ -92,6 +104,18 @@ class HashSumValue
          memset(Sum,0,sizeof(Sum));
          Set(Str);
    }
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+   APT_HIDDEN explicit HashSumValue(APT::StringView const &Str)
+   {
+         memset(Sum,0,sizeof(Sum));
+         Set(Str);
+   }
+   APT_HIDDEN explicit HashSumValue(const char *Str)
+   {
+         memset(Sum,0,sizeof(Sum));
+         Set(Str);
+   }
+#endif
    HashSumValue()
    {
       memset(Sum,0,sizeof(Sum));

+ 6 - 1
apt-pkg/contrib/strutl.cc

@@ -1113,13 +1113,18 @@ static int HexDigit(int c)
 // ---------------------------------------------------------------------
 /* The length of the buffer must be exactly 1/2 the length of the string. */
 bool Hex2Num(const string &Str,unsigned char *Num,unsigned int Length)
+{
+   return Hex2Num(APT::StringView(Str), Num, Length);
+}
+
+bool Hex2Num(const APT::StringView Str,unsigned char *Num,unsigned int Length)
 {
    if (Str.length() != Length*2)
       return false;
    
    // Convert each digit. We store it in the same order as the string
    int J = 0;
-   for (string::const_iterator I = Str.begin(); I != Str.end();J++, I += 2)
+   for (auto I = Str.begin(); I != Str.end();J++, I += 2)
    {
       int first_half = HexDigit(I[0]);
       int second_half;

+ 6 - 1
apt-pkg/contrib/strutl.h

@@ -22,6 +22,9 @@
 #include <cstring>
 #include <vector>
 #include <iostream>
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+#include <apt-pkg/string_view.h>
+#endif
 #include <time.h>
 #include <stddef.h>
 
@@ -75,7 +78,9 @@ bool StrToNum(const char *Str,unsigned long long &Res,unsigned Len,unsigned Base
 bool Base256ToNum(const char *Str,unsigned long &Res,unsigned int Len);
 bool Base256ToNum(const char *Str,unsigned long long &Res,unsigned int Len);
 bool Hex2Num(const std::string &Str,unsigned char *Num,unsigned int Length);
-
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+APT_HIDDEN bool Hex2Num(const APT::StringView Str,unsigned char *Num,unsigned int Length);
+#endif
 // input changing string split
 bool TokSplitString(char Tok,char *Input,char **List,
 		    unsigned long ListMax);

+ 72 - 44
apt-pkg/deb/deblistparser.cc

@@ -34,6 +34,7 @@
 									/*}}}*/
 
 using std::string;
+using APT::StringView;
 
 static const debListParser::WordList PrioList[] = {
    {"required",pkgCache::State::Required},
@@ -57,7 +58,7 @@ debListParser::debListParser(FileFd *File) :
 // ---------------------------------------------------------------------
 /* This is to return the name of the package this section describes */
 string debListParser::Package() {
-   string Result = Section.FindS("Package");
+   string Result = Section.Find("Package").to_string();
 
    // Normalize mixed case package names to lower case, like dpkg does
    // See Bug#807012 for details
@@ -72,15 +73,15 @@ string debListParser::Package() {
 // ---------------------------------------------------------------------
 /* This will return the Architecture of the package this section describes */
 string debListParser::Architecture() {
-   std::string const Arch = Section.FindS("Architecture");
-   return Arch.empty() ? "none" : Arch;
+   auto const Arch = Section.Find("Architecture");
+   return Arch.empty() ? "none" : Arch.to_string();
 }
 									/*}}}*/
 // ListParser::ArchitectureAll						/*{{{*/
 // ---------------------------------------------------------------------
 /* */
 bool debListParser::ArchitectureAll() {
-   return Section.FindS("Architecture") == "all";
+   return Section.Find("Architecture") == "all";
 }
 									/*}}}*/
 // ListParser::Version - Return the version string			/*{{{*/
@@ -90,13 +91,13 @@ bool debListParser::ArchitectureAll() {
    entry is assumed to only describe package properties */
 string debListParser::Version()
 {
-   return Section.FindS("Version");
+   return Section.Find("Version").to_string();
 }
 									/*}}}*/
 unsigned char debListParser::ParseMultiArch(bool const showErrors)	/*{{{*/
 {
    unsigned char MA;
-   string const MultiArch = Section.FindS("Multi-Arch");
+   auto const MultiArch = Section.Find("Multi-Arch");
    if (MultiArch.empty() == true || MultiArch == "no")
       MA = pkgCache::Version::No;
    else if (MultiArch == "same") {
@@ -118,7 +119,7 @@ unsigned char debListParser::ParseMultiArch(bool const showErrors)	/*{{{*/
    {
       if (showErrors == true)
 	 _error->Warning("Unknown Multi-Arch type '%s' for package '%s'",
-	       MultiArch.c_str(), Section.FindS("Package").c_str());
+	       MultiArch.to_string().c_str(), Section.FindS("Package").c_str());
       MA = pkgCache::Version::No;
    }
 
@@ -204,7 +205,7 @@ bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
    // Priority
    if (Section.Find("Priority",Start,Stop) == true)
    {
-      if (GrabWord(string(Start,Stop-Start),PrioList,Ver->Priority) == false)
+      if (GrabWord(StringView(Start,Stop-Start),PrioList,Ver->Priority) == false)
 	 Ver->Priority = pkgCache::State::Extra;
    }
 
@@ -240,11 +241,16 @@ bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
    form. If this returns the blank string then the entry is assumed to
    only describe package properties */
 string debListParser::Description(std::string const &lang)
+{
+   return Description(StringView(lang)).to_string();
+}
+
+StringView debListParser::Description(StringView lang)
 {
    if (lang.empty())
-      return Section.FindS("Description");
+      return Section.Find("Description");
    else
-      return Section.FindS(string("Description-").append(lang).c_str());
+      return Section.Find(string("Description-").append(lang.data(), lang.size()));
 }
 									/*}}}*/
 // ListParser::AvailableDescriptionLanguages				/*{{{*/
@@ -271,15 +277,16 @@ std::vector<std::string> debListParser::AvailableDescriptionLanguages()
  */
 MD5SumValue debListParser::Description_md5()
 {
-   string const value = Section.FindS("Description-md5");
+   auto const value = Section.Find("Description-md5");
    if (value.empty() == true)
    {
-      std::string const desc = Description("") + "\n";
+      StringView desc = Description(StringView("", 0));
       if (desc == "\n")
 	 return MD5SumValue();
 
       MD5Summation md5;
-      md5.Add(desc.c_str());
+      md5.Add(desc.data(), desc.size());
+      md5.Add("\n");
       return md5.Result();
    }
    else if (likely(value.size() == 32))
@@ -288,10 +295,10 @@ MD5SumValue debListParser::Description_md5()
       if (sumvalue.Set(value))
 	 return sumvalue;
 
-      _error->Error("Malformed Description-md5 line; includes invalid character '%s'", value.c_str());
+      _error->Error("Malformed Description-md5 line; includes invalid character '%.*s'", (int)value.length(), value.data());
       return MD5SumValue();
    }
-   _error->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value.size(), value.c_str());
+   _error->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%.*s'", (int)value.size(), (int)value.length(), value.data());
    return MD5SumValue();
 }
                                                                         /*}}}*/
@@ -332,21 +339,21 @@ bool debListParser::UsePackage(pkgCache::PkgIterator &Pkg,
 /* */
 unsigned short debListParser::VersionHash()
 {
-   const char *Sections[] ={"Installed-Size",
+   static const StringView Sections[] ={"Installed-Size",
                             "Depends",
                             "Pre-Depends",
 //                            "Suggests",
 //                            "Recommends",
                             "Conflicts",
                             "Breaks",
-                            "Replaces",0};
+                            "Replaces"};
    unsigned long Result = INIT_FCS;
    char S[1024];
-   for (const char * const *I = Sections; *I != 0; ++I)
+   for (StringView I : Sections)
    {
       const char *Start;
       const char *End;
-      if (Section.Find(*I,Start,End) == false || End - Start >= (signed)sizeof(S))
+      if (Section.Find(I,Start,End) == false || End - Start >= (signed)sizeof(S))
 	 continue;
       
       /* Strip out any spaces from the text, this undoes dpkgs reformatting
@@ -410,7 +417,7 @@ bool debStatusListParser::ParseStatus(pkgCache::PkgIterator &Pkg,
                           {"deinstall",pkgCache::State::DeInstall},
                           {"purge",pkgCache::State::Purge},
                           {NULL, 0}};
-   if (GrabWord(string(Start,I-Start),WantList,Pkg->SelectedState) == false)
+   if (GrabWord(StringView(Start,I-Start),WantList,Pkg->SelectedState) == false)
       return _error->Error("Malformed 1st word in the Status line");
 
    // Isloate the next word
@@ -426,7 +433,7 @@ bool debStatusListParser::ParseStatus(pkgCache::PkgIterator &Pkg,
                           {"hold",pkgCache::State::HoldInst},
                           {"hold-reinstreq",pkgCache::State::HoldReInstReq},
                           {NULL, 0}};
-   if (GrabWord(string(Start,I-Start),FlagList,Pkg->InstState) == false)
+   if (GrabWord(StringView(Start,I-Start),FlagList,Pkg->InstState) == false)
       return _error->Error("Malformed 2nd word in the Status line");
 
    // Isloate the last word
@@ -446,7 +453,7 @@ bool debStatusListParser::ParseStatus(pkgCache::PkgIterator &Pkg,
                             {"triggers-pending",pkgCache::State::TriggersPending},
                             {"installed",pkgCache::State::Installed},
                             {NULL, 0}};
-   if (GrabWord(string(Start,I-Start),StatusList,Pkg->CurrentState) == false)
+   if (GrabWord(StringView(Start,I-Start),StatusList,Pkg->CurrentState) == false)
       return _error->Error("Malformed 3rd word in the Status line");
 
    /* A Status line marks the package as indicating the current
@@ -543,6 +550,22 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop,
 					unsigned int &Op, bool const &ParseArchFlags,
 					bool const &StripMultiArch,
 					bool const &ParseRestrictionsList)
+{
+   StringView PackageView;
+   StringView VerView;
+
+   auto res = ParseDepends(Start, Stop, PackageView, VerView, Op, (bool)ParseArchFlags,
+   (bool) StripMultiArch, (bool) ParseRestrictionsList);
+   Package = PackageView.to_string();
+   Ver = VerView.to_string();
+
+   return res;
+}
+const char *debListParser::ParseDepends(const char *Start,const char *Stop,
+					StringView &Package,StringView &Ver,
+					unsigned int &Op, bool ParseArchFlags,
+					bool StripMultiArch,
+					bool ParseRestrictionsList)
 {
    // Strip off leading space
    for (;Start != Stop && isspace_ascii(*Start) != 0; ++Start);
@@ -561,16 +584,16 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop,
       return 0;
    
    // Stash the package name
-   Package.assign(Start,I - Start);
+   Package = StringView(Start, I - Start);
 
    // We don't want to confuse library users which can't handle MultiArch
    if (StripMultiArch == true) {
       string const arch = _config->Find("APT::Architecture");
       size_t const found = Package.rfind(':');
-      if (found != string::npos &&
-	  (strcmp(Package.c_str() + found, ":any") == 0 ||
-	   strcmp(Package.c_str() + found, ":native") == 0 ||
-	   strcmp(Package.c_str() + found + 1, arch.c_str()) == 0))
+      if (found != StringView::npos &&
+	  (Package.compare(found, Package.size(), ":any") == 0 ||
+	   Package.compare(found, Package.size(), ":native") == 0||
+	   Package.compare(found +1, Package.size(), arch) == 0))
 	 Package = Package.substr(0,found);
    }
 
@@ -597,12 +620,12 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop,
       const char *End = I;
       for (; End > Start && isspace_ascii(End[-1]); End--);
       
-      Ver.assign(Start,End-Start);
+      Ver = StringView(Start,End-Start);
       I++;
    }
    else
    {
-      Ver.clear();
+      Ver = StringView();
       Op = pkgCache::Dep::NoOp;
    }
    
@@ -790,8 +813,8 @@ bool debListParser::ParseDepends(pkgCache::VerIterator &Ver,
 
    while (1)
    {
-      string Package;
-      string Version;
+      StringView Package;
+      StringView Version;
       unsigned int Op;
 
       Start = ParseDepends(Start, Stop, Package, Version, Op, false, false, false);
@@ -804,7 +827,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator &Ver,
 	 if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false)
 	    return false;
       }
-      else if (strcmp(Package.c_str() + found, ":any") == 0)
+      else if (Package.compare(found, Package.npos, ":any") == 0)
       {
 	 if (NewDepends(Ver,Package,"any",Version,Op,Type) == false)
 	    return false;
@@ -813,10 +836,12 @@ bool debListParser::ParseDepends(pkgCache::VerIterator &Ver,
       {
 	 // Such dependencies are not supposed to be accepted …
 	 // … but this is probably the best thing to do anyway
+	 std::string Pkg;
 	 if (Package.substr(found + 1) == "native")
-	    Package = Package.substr(0, found) + ':' + Ver.Cache()->NativeArch();
-
-	 if (NewDepends(Ver, Package, "any", Version, Op | pkgCache::Dep::ArchSpecific, Type) == false)
+	    Pkg = Package.substr(0, found).to_string() + ':' + Ver.Cache()->NativeArch();
+	 else
+	    Pkg = Package.to_string();
+	 if (NewDepends(Ver, Pkg, "any", Version, Op | pkgCache::Dep::ArchSpecific, Type) == false)
 	    return false;
       }
 
@@ -852,8 +877,8 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
    const char *Stop;
    if (Section.Find("Provides",Start,Stop) == true)
    {
-      string Package;
-      string Version;
+      StringView Package;
+      StringView Version;
       unsigned int Op;
 
       do
@@ -862,10 +887,10 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
 	 const size_t archfound = Package.rfind(':');
 	 if (Start == 0)
 	    return _error->Error("Problem parsing Provides line");
-	 if (Op != pkgCache::Dep::NoOp && Op != pkgCache::Dep::Equals) {
-	    _error->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package.c_str());
+	 if (unlikely(Op != pkgCache::Dep::NoOp && Op != pkgCache::Dep::Equals)) {
+	    _error->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package.to_string().c_str());
 	 } else if (archfound != string::npos) {
-	    std::string spzArch = Package.substr(archfound + 1);
+	    StringView spzArch = Package.substr(archfound + 1);
 	    if (spzArch != "any")
 	    {
 	       if (NewProvides(Ver, Package.substr(0, archfound), spzArch, Version, pkgCache::Flag::MultiArchImplicit | pkgCache::Flag::ArchSpecific) == false)
@@ -880,7 +905,7 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
 	 } else {
 	    if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed)
 	    {
-	       if (NewProvides(Ver, Package + ":any", "any", Version, pkgCache::Flag::MultiArchImplicit) == false)
+	       if (NewProvides(Ver, Package.to_string().append(":any"), "any", Version, pkgCache::Flag::MultiArchImplicit) == false)
 		  return false;
 	    }
 	    if (NewProvides(Ver, Package, Arch, Version, 0) == false)
@@ -888,7 +913,9 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
 	 }
 	 if (archfound == std::string::npos)
 	 {
-	    std::string const spzName = Package + ':' + Ver.ParentPkg().Arch();
+	    string spzName = Package.to_string();
+	    spzName.push_back(':');
+	    spzName.append(Ver.ParentPkg().Arch());
 	    pkgCache::PkgIterator const spzPkg = Ver.Cache()->FindPkg(spzName, "any");
 	    if (spzPkg.end() == false)
 	    {
@@ -929,11 +956,12 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
 // ListParser::GrabWord - Matches a word and returns			/*{{{*/
 // ---------------------------------------------------------------------
 /* Looks for a word in a list of words - for ParseStatus */
-bool debListParser::GrabWord(string Word,const WordList *List,unsigned char &Out)
+bool debListParser::GrabWord(StringView Word,const WordList *List,unsigned char &Out)
 {
    for (unsigned int C = 0; List[C].Str != 0; C++)
    {
-      if (strcasecmp(Word.c_str(),List[C].Str) == 0)
+      if (Word.length() == strlen(List[C].Str) &&
+	  strncasecmp(Word.data(),List[C].Str,Word.length()) == 0)
       {
 	 Out = List[C].Val;
 	 return true;

+ 18 - 1
apt-pkg/deb/deblistparser.h

@@ -19,6 +19,9 @@
 
 #include <string>
 #include <vector>
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+#include <apt-pkg/string_view.h>
+#endif
 
 #ifndef APT_8_CLEANER_HEADERS
 #include <apt-pkg/indexfile.h>
@@ -50,7 +53,10 @@ class APT_HIDDEN debListParser : public pkgCacheListParser
    bool ParseDepends(pkgCache::VerIterator &Ver,const char *Tag,
 		     unsigned int Type);
    bool ParseProvides(pkgCache::VerIterator &Ver);
-   static bool GrabWord(std::string Word,const WordList *List,unsigned char &Out);
+
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+   APT_HIDDEN static bool GrabWord(APT::StringView Word,const WordList *List,unsigned char &Out);
+#endif
    APT_HIDDEN unsigned char ParseMultiArch(bool const showErrors);
 
    public:
@@ -64,6 +70,9 @@ class APT_HIDDEN debListParser : public pkgCacheListParser
    virtual std::string Version() APT_OVERRIDE;
    virtual bool NewVersion(pkgCache::VerIterator &Ver) APT_OVERRIDE;
    virtual std::string Description(std::string const &lang) APT_OVERRIDE;
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+   APT::StringView Description(APT::StringView lang);
+#endif
    virtual std::vector<std::string> AvailableDescriptionLanguages() APT_OVERRIDE;
    virtual MD5SumValue Description_md5() APT_OVERRIDE;
    virtual unsigned short VersionHash() APT_OVERRIDE;
@@ -91,6 +100,14 @@ class APT_HIDDEN debListParser : public pkgCacheListParser
 	 bool const &ParseArchFlags, bool const &StripMultiArch,
 	 bool const &ParseRestrictionsList);
 
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+   APT_HIDDEN static const char *ParseDepends(const char *Start,const char *Stop,
+	 APT::StringView &Package,
+    APT::StringView &Ver,unsigned int &Op,
+	 bool const ParseArchFlags = false, bool StripMultiArch = true,
+	 bool const ParseRestrictionsList = false);
+#endif
+
    APT_PUBLIC static const char *ConvertRelation(const char *I,unsigned int &Op);
 
    debListParser(FileFd *File);

+ 1 - 0
apt-pkg/makefile

@@ -12,6 +12,7 @@ include ../buildlib/defaults.mak
 # The library name and version (indirectly used from init.h)
 include ../buildlib/libversion.mak
 
+CXXFLAGS+=-DAPT_PKG_EXPOSE_STRING_VIEW
 LIBRARY=apt-pkg
 MAJOR=$(LIBAPTPKG_MAJOR)
 MINOR=$(LIBAPTPKG_RELEASE)

+ 32 - 6
apt-pkg/pkgcache.cc

@@ -45,6 +45,7 @@
 									/*}}}*/
 
 using std::string;
+using APT::StringView;
 
 
 // Cache::Header::Header - Constructor					/*{{{*/
@@ -206,6 +207,13 @@ bool pkgCache::ReMap(bool const &Errorchecks)
 /* This is used to generate the hash entries for the HashTable. With my
    package list from bo this function gets 94% table usage on a 512 item
    table (480 used items) */
+map_id_t pkgCache::sHash(StringView Str) const
+{
+   uint32_t Hash = 5381;
+   for (auto I = Str.begin(); I != Str.end(); ++I)
+      Hash = 33 * Hash + tolower_ascii(*I);
+   return Hash % HeaderP->GetHashTableSize();
+}
 map_id_t pkgCache::sHash(const string &Str) const
 {
    uint32_t Hash = 5381;
@@ -251,10 +259,14 @@ uint32_t pkgCache::CacheHash()
 // ---------------------------------------------------------------------
 /* Returns 0 on error, pointer to the package otherwise */
 pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) {
-	size_t const found = Name.find(':');
+   return FindPkg(StringView(Name));
+}
+
+pkgCache::PkgIterator pkgCache::FindPkg(StringView Name) {
+	auto const found = Name.find(':');
 	if (found == string::npos)
 	   return FindPkg(Name, "native");
-	string const Arch = Name.substr(found+1);
+	auto const Arch = Name.substr(found+1);
 	/* Beware: This is specialcased to handle pkg:any in dependencies
 	   as these are linked to virtual pkg:any named packages.
 	   If you want any arch from a pkg, use FindPkg(pkg,"any") */
@@ -267,6 +279,10 @@ pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) {
 // ---------------------------------------------------------------------
 /* Returns 0 on error, pointer to the package otherwise */
 pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string const &Arch) {
+   return FindPkg(StringView(Name), StringView(Arch));
+}
+
+pkgCache::PkgIterator pkgCache::FindPkg(StringView Name, StringView Arch) {
 	/* We make a detour via the GrpIterator here as
 	   on a multi-arch environment a group is easier to
 	   find than a package (less entries in the buckets) */
@@ -281,13 +297,17 @@ pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string const &Arch)
 // ---------------------------------------------------------------------
 /* Returns End-Pointer on error, pointer to the group otherwise */
 pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) {
+   return FindGrp(StringView(Name));
+}
+
+pkgCache::GrpIterator pkgCache::FindGrp(StringView Name) {
 	if (unlikely(Name.empty() == true))
 		return GrpIterator(*this,0);
 
 	// Look at the hash bucket for the group
 	Group *Grp = GrpP + HeaderP->GrpHashTableP()[sHash(Name)];
 	for (; Grp != GrpP; Grp = GrpP + Grp->Next) {
-		int const cmp = strcmp(Name.c_str(), StrP + Grp->Name);
+		int const cmp = Name.compare(StrP + Grp->Name);
 		if (cmp == 0)
 			return GrpIterator(*this, Grp);
 		else if (cmp < 0)
@@ -350,6 +370,12 @@ const char *pkgCache::Priority(unsigned char Prio)
 // ---------------------------------------------------------------------
 /* Returns an End-Pointer on error, pointer to the package otherwise */
 pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const {
+   return FindPkg(StringView(Arch));
+}
+pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(const char *Arch) const {
+   return FindPkg(StringView(Arch));
+}
+pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(StringView Arch) const {
 	if (unlikely(IsGood() == false || S->FirstPackage == 0))
 		return PkgIterator(*Owner, 0);
 
@@ -363,7 +389,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const {
 	// Iterate over the list to find the matching arch
 	for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP;
 	     Pkg = Owner->PkgP + Pkg->NextPackage) {
-		if (stringcmp(Arch, Owner->StrP + Pkg->Arch) == 0)
+		if (Arch.compare(Owner->StrP + Pkg->Arch) == 0)
 			return PkgIterator(*Owner, Pkg);
 		if ((Owner->PkgP + S->LastPackage) == Pkg)
 			break;
@@ -376,7 +402,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const {
 // ---------------------------------------------------------------------
 /* Returns an End-Pointer on error, pointer to the package otherwise */
 pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg(bool const &PreferNonVirtual) const {
-	pkgCache::PkgIterator Pkg = FindPkg("native");
+	pkgCache::PkgIterator Pkg = FindPkg(StringView("native", 6));
 	if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
 		return Pkg;
 
@@ -388,7 +414,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg(bool const &Prefer
 			return Pkg;
 	}
 	// packages without an architecture
-	Pkg = FindPkg("none");
+	Pkg = FindPkg(StringView("none", 4));
 	if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
 		return Pkg;
 

+ 16 - 1
apt-pkg/pkgcache.h

@@ -81,6 +81,10 @@
 #include <time.h>
 #include <stdint.h>
 
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+#include <apt-pkg/string_view.h>
+#endif
+
 #ifndef APT_8_CLEANER_HEADERS
 using std::string;
 #endif
@@ -193,7 +197,9 @@ class pkgCache								/*{{{*/
    // Memory mapped cache file
    std::string CacheFile;
    MMap &Map;
-
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+   APT_HIDDEN map_id_t sHash(APT::StringView S) const APT_PURE;
+#endif
    map_id_t sHash(const std::string &S) const APT_PURE;
    map_id_t sHash(const char *S) const APT_PURE;
    
@@ -221,6 +227,9 @@ class pkgCache								/*{{{*/
    inline void *DataEnd() {return ((unsigned char *)Map.Data()) + Map.Size();}
       
    // String hashing function (512 range)
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+   APT_HIDDEN inline map_id_t Hash(APT::StringView S) const {return sHash(S);}
+#endif
    inline map_id_t Hash(const std::string &S) const {return sHash(S);}
    inline map_id_t Hash(const char *S) const {return sHash(S);}
 
@@ -230,6 +239,12 @@ class pkgCache								/*{{{*/
    static const char *Priority(unsigned char Priority);
    
    // Accessors
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+   APT_HIDDEN GrpIterator FindGrp(APT::StringView Name);
+   APT_HIDDEN PkgIterator FindPkg(APT::StringView Name);
+   APT_HIDDEN PkgIterator FindPkg(APT::StringView Name, APT::StringView Arch);
+#endif
+
    GrpIterator FindGrp(const std::string &Name);
    PkgIterator FindPkg(const std::string &Name);
    PkgIterator FindPkg(const std::string &Name, const std::string &Arch);

+ 22 - 21
apt-pkg/pkgcachegen.cc

@@ -49,6 +49,7 @@ static bool IsDuplicateDescription(pkgCache::DescIterator Desc,
 			    MD5SumValue const &CurMd5, std::string const &CurLang);
 
 using std::string;
+using APT::StringView;
 
 // CacheGenerator::pkgCacheGenerator - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
@@ -501,7 +502,7 @@ bool pkgCacheGenerator::AddNewDescription(ListParser &List, pkgCache::VerIterato
 // CacheGenerator::NewGroup - Add a new group				/*{{{*/
 // ---------------------------------------------------------------------
 /* This creates a new group structure and adds it to the hash table */
-bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name)
+bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, StringView Name)
 {
    Grp = Cache.FindGrp(Name);
    if (Grp.end() == false)
@@ -513,7 +514,7 @@ bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name)
       return false;
 
    Grp = pkgCache::GrpIterator(Cache, Cache.GrpP + Group);
-   map_stringitem_t const idxName = StoreString(PKGNAME, Name);
+   map_stringitem_t const idxName = StoreString(PKGNAME, Name.to_string());
    if (unlikely(idxName == 0))
       return false;
    Grp->Name = idxName;
@@ -521,7 +522,7 @@ bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name)
    // Insert it into the hash table
    unsigned long const Hash = Cache.Hash(Name);
    map_pointer_t *insertAt = &Cache.HeaderP->GrpHashTableP()[Hash];
-   while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.GrpP + *insertAt)->Name) > 0)
+   while (*insertAt != 0 && Name.compare(Cache.StrP + (Cache.GrpP + *insertAt)->Name) > 0)
       insertAt = &(Cache.GrpP + *insertAt)->Next;
    Grp->Next = *insertAt;
    *insertAt = Group;
@@ -533,8 +534,8 @@ bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name)
 // CacheGenerator::NewPackage - Add a new package			/*{{{*/
 // ---------------------------------------------------------------------
 /* This creates a new package structure and adds it to the hash table */
-bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name,
-					const string &Arch) {
+bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg, StringView Name,
+					StringView Arch) {
    pkgCache::GrpIterator Grp;
    Dynamic<pkgCache::GrpIterator> DynGrp(Grp);
    if (unlikely(NewGroup(Grp, Name) == false))
@@ -554,7 +555,7 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name
    APT_IGNORE_DEPRECATED(Pkg->Name = Grp->Name;)
    Pkg->Group = Grp.Index();
    // all is mapped to the native architecture
-   map_stringitem_t const idxArch = (Arch == "all") ? Cache.HeaderP->Architecture : StoreString(MIXED, Arch);
+   map_stringitem_t const idxArch = (Arch == "all") ? Cache.HeaderP->Architecture : StoreString(MIXED, Arch.to_string());
    if (unlikely(idxArch == 0))
       return false;
    Pkg->Arch = idxArch;
@@ -567,7 +568,7 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name
       // Insert it into the hash table
       map_id_t const Hash = Cache.Hash(Name);
       map_pointer_t *insertAt = &Cache.HeaderP->PkgHashTableP()[Hash];
-      while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.GrpP + (Cache.PkgP + *insertAt)->Group)->Name) > 0)
+      while (*insertAt != 0 && Name.compare(Cache.StrP + (Cache.GrpP + (Cache.PkgP + *insertAt)->Group)->Name) > 0)
 	 insertAt = &(Cache.PkgP + *insertAt)->NextPackage;
       Pkg->NextPackage = *insertAt;
       *insertAt = Package;
@@ -640,8 +641,8 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name
    if (Arch == "any")
    {
       size_t const found = Name.find(':');
-      std::string const NameA = Name.substr(0, found);
-      std::string const ArchA = Name.substr(found + 1);
+      StringView const NameA = Name.substr(0, found);
+      StringView const ArchA = Name.substr(found + 1);
       pkgCache::PkgIterator PkgA = Cache.FindPkg(NameA, ArchA);
       if (PkgA.end() == false)
       {
@@ -997,9 +998,9 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
 /* This creates a Group and the Package to link this dependency to if
    needed and handles also the caching of the old endpoint */
 bool pkgCacheListParser::NewDepends(pkgCache::VerIterator &Ver,
-					       const string &PackageName,
-					       const string &Arch,
-					       const string &Version,
+					       StringView PackageName,
+					       StringView Arch,
+					       StringView Version,
 					       uint8_t const Op,
 					       uint8_t const Type)
 {
@@ -1013,12 +1014,12 @@ bool pkgCacheListParser::NewDepends(pkgCache::VerIterator &Ver,
    {
       int const CmpOp = Op & 0x0F;
       // =-deps are used (79:1) for lockstep on same-source packages (e.g. data-packages)
-      if (CmpOp == pkgCache::Dep::Equals && strcmp(Version.c_str(), Ver.VerStr()) == 0)
+      if (CmpOp == pkgCache::Dep::Equals && Version.compare(Ver.VerStr()) == 0)
 	 idxVersion = Ver->VerStr;
 
       if (idxVersion == 0)
       {
-	 idxVersion = StoreString(pkgCacheGenerator::VERSIONNUMBER, Version);
+	 idxVersion = StoreString(pkgCacheGenerator::VERSIONNUMBER, Version.to_string());
 	 if (unlikely(idxVersion == 0))
 	    return false;
       }
@@ -1066,9 +1067,9 @@ bool pkgCacheListParser::NewDepends(pkgCache::VerIterator &Ver,
 									/*}}}*/
 // ListParser::NewProvides - Create a Provides element			/*{{{*/
 bool pkgCacheListParser::NewProvides(pkgCache::VerIterator &Ver,
-						const string &PkgName,
-						const string &PkgArch,
-						const string &Version,
+						StringView PkgName,
+						StringView PkgArch,
+						StringView Version,
 						uint8_t const Flags)
 {
    pkgCache const &Cache = Owner->Cache;
@@ -1087,7 +1088,7 @@ bool pkgCacheListParser::NewProvides(pkgCache::VerIterator &Ver,
 
    map_stringitem_t idxProvideVersion = 0;
    if (Version.empty() == false) {
-      idxProvideVersion = StoreString(pkgCacheGenerator::VERSIONNUMBER, Version);
+      idxProvideVersion = StoreString(pkgCacheGenerator::VERSIONNUMBER, Version.to_string());
       if (unlikely(idxProvideVersion == 0))
 	 return false;
    }
@@ -1120,8 +1121,8 @@ bool pkgCacheGenerator::NewProvides(pkgCache::VerIterator &Ver,
 }
 									/*}}}*/
 // ListParser::NewProvidesAllArch - add provides for all architectures	/*{{{*/
-bool pkgCacheListParser::NewProvidesAllArch(pkgCache::VerIterator &Ver, string const &Package,
-				string const &Version, uint8_t const Flags) {
+bool pkgCacheListParser::NewProvidesAllArch(pkgCache::VerIterator &Ver, StringView Package,
+				StringView Version, uint8_t const Flags) {
    pkgCache &Cache = Owner->Cache;
    pkgCache::GrpIterator Grp = Cache.FindGrp(Package);
    Dynamic<pkgCache::GrpIterator> DynGrp(Grp);
@@ -1132,7 +1133,7 @@ bool pkgCacheListParser::NewProvidesAllArch(pkgCache::VerIterator &Ver, string c
    {
       map_stringitem_t idxProvideVersion = 0;
       if (Version.empty() == false) {
-	 idxProvideVersion = StoreString(pkgCacheGenerator::VERSIONNUMBER, Version);
+	 idxProvideVersion = StoreString(pkgCacheGenerator::VERSIONNUMBER, Version.to_string());
 	 if (unlikely(idxProvideVersion == 0))
 	    return false;
       }

+ 15 - 9
apt-pkg/pkgcachegen.h

@@ -29,6 +29,9 @@
 #if __cplusplus >= 201103L
 #include <unordered_map>
 #endif
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+#include <apt-pkg/string_view.h>
+#endif
 
 class FileFd;
 class pkgSourceList;
@@ -79,8 +82,10 @@ class APT_HIDDEN pkgCacheGenerator					/*{{{*/
    std::string PkgFileName;
    pkgCache::PackageFile *CurrentFile;
 
-   bool NewGroup(pkgCache::GrpIterator &Grp,const std::string &Name);
-   bool NewPackage(pkgCache::PkgIterator &Pkg,const std::string &Name, const std::string &Arch);
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+   bool NewGroup(pkgCache::GrpIterator &Grp, APT::StringView Name);
+   bool NewPackage(pkgCache::PkgIterator &Pkg, APT::StringView Name, APT::StringView Arch);
+#endif
    bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List);
    bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List);
    bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver,
@@ -156,15 +161,16 @@ class APT_HIDDEN pkgCacheListParser
 
    inline map_stringitem_t WriteString(const std::string &S) {return Owner->WriteStringInMap(S);};
    inline map_stringitem_t WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);};
-   bool NewDepends(pkgCache::VerIterator &Ver,const std::string &Package, const std::string &Arch,
-		   const std::string &Version,uint8_t const Op,
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+   bool NewDepends(pkgCache::VerIterator &Ver,APT::StringView Package, APT::StringView Arch,
+		   APT::StringView Version,uint8_t const Op,
 		   uint8_t const Type);
-   bool NewProvides(pkgCache::VerIterator &Ver,const std::string &PkgName,
-		    const std::string &PkgArch, const std::string &Version,
+   bool NewProvides(pkgCache::VerIterator &Ver,APT::StringView PkgName,
+		    APT::StringView PkgArch, APT::StringView Version,
 		    uint8_t const Flags);
-   bool NewProvidesAllArch(pkgCache::VerIterator &Ver, std::string const &Package,
-			   std::string const &Version, uint8_t const Flags);
-   
+   bool NewProvidesAllArch(pkgCache::VerIterator &Ver, APT::StringView Package,
+			   APT::StringView Version, uint8_t const Flags);
+#endif
    public:
    
    // These all operate against the current section

+ 76 - 0
apt-pkg/tagfile-compat.cc

@@ -0,0 +1,76 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: tagfile.cc,v 1.37.2.2 2003/12/31 16:02:30 mdz Exp $
+/* ######################################################################
+
+   Fast scanner for RFC-822 type header information
+
+   This uses a rotating buffer to load the package information into.
+   The scanner runs over it and isolates and indexes a single section.
+
+   This defines compat functions for the external code.
+
+   ##################################################################### */
+									/*}}}*/
+
+#include<config.h>
+#define APT_COMPILING_TAGFILE_COMPAT_CC
+#include <apt-pkg/tagfile.h>
+
+using std::string;
+using APT::StringView;
+
+
+bool pkgTagSection::Exists(const char* const Tag) const
+{
+   return Exists(StringView(Tag));
+}
+
+bool pkgTagSection::Find(const char *Tag,unsigned int &Pos) const
+{
+   return Find(StringView(Tag), Pos);
+}
+
+bool pkgTagSection::Find(const char *Tag,const char *&Start,
+		         const char *&End) const
+{
+   return Find(StringView(Tag), Start, End);
+}
+
+string pkgTagSection::FindS(const char *Tag) const
+{
+   return Find(StringView(Tag)).to_string();
+}
+
+string pkgTagSection::FindRawS(const char *Tag) const
+{
+   return FindRaw(StringView(Tag)).to_string();
+}
+
+signed int pkgTagSection::FindI(const char *Tag,signed long Default) const
+{
+    return FindI(StringView(Tag), Default);
+}
+
+unsigned long long pkgTagSection::FindULL(const char *Tag, unsigned long long const &Default) const
+{
+   return FindULL(StringView(Tag), Default);
+}
+									/*}}}*/
+
+bool pkgTagSection::FindB(const char *Tag, bool const &Default) const
+{
+   return FindB(StringView(Tag), Default);
+}
+
+bool pkgTagSection::FindFlag(const char * const Tag, uint8_t &Flags,
+			     uint8_t const Flag) const
+{
+    return FindFlag(StringView(Tag), Flags, Flag);
+}
+
+bool pkgTagSection::FindFlag(const char *Tag,unsigned long &Flags,
+			     unsigned long Flag) const
+{
+   return FindFlag(StringView(Tag), Flags, Flag);
+}

+ 25 - 21
apt-pkg/tagfile.cc

@@ -17,6 +17,7 @@
 #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 +31,7 @@
 									/*}}}*/
 
 using std::string;
+using APT::StringView;
 
 class APT_HIDDEN pkgTagFilePrivate					/*{{{*/
 {
@@ -607,7 +609,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,9 +618,10 @@ 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(StringView TagView,unsigned int &Pos) const
 {
-   size_t const Length = strlen(Tag);
+   const char * const Tag = TagView.data();
+   size_t const Length = TagView.length();
    unsigned int Bucket = AlphaIndexes[AlphaHash(Tag, Length)];
    if (Bucket == 0)
       return false;
@@ -639,7 +642,8 @@ 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::Find(StringView Tag,const char *&Start,
 		         const char *&End) const
 {
    unsigned int Pos;
@@ -658,17 +662,17 @@ bool pkgTagSection::Find(const char *Tag,const char *&Start,
 }
 									/*}}}*/
 // 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);
 }
 									/*}}}*/
 // TagSection::FindRawS - Find a string					/*{{{*/
-string pkgTagSection::FindRawS(const char *Tag) const
+StringView pkgTagSection::FindRaw(StringView Tag) const
 {
    unsigned int Pos;
    if (Find(Tag, Pos) == false)
@@ -682,13 +686,13 @@ 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);
 }
 									/*}}}*/
 // TagSection::FindI - Find an integer					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-signed int pkgTagSection::FindI(const char *Tag,signed long Default) const
+signed int pkgTagSection::FindI(StringView Tag,signed long Default) const
 {
    const char *Start;
    const char *Stop;
@@ -718,7 +722,7 @@ signed int pkgTagSection::FindI(const char *Tag,signed long Default) const
 // 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::FindULL(StringView Tag, unsigned long long const &Default) const
 {
    const char *Start;
    const char *Stop;
@@ -742,7 +746,7 @@ unsigned long long pkgTagSection::FindULL(const char *Tag, unsigned long long co
 // TagSection::FindB - Find boolean value                		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool pkgTagSection::FindB(const char *Tag, bool const &Default) const
+bool pkgTagSection::FindB(StringView Tag, bool Default) const
 {
    const char *Start, *Stop;
    if (Find(Tag, Start, Stop) == false)
@@ -753,7 +757,7 @@ bool pkgTagSection::FindB(const char *Tag, bool const &Default) const
 // 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::FindFlag(StringView Tag, uint8_t &Flags,
 			     uint8_t const Flag) const
 {
    const char *Start;
@@ -781,7 +785,7 @@ bool pkgTagSection::FindFlag(uint8_t &Flags, uint8_t const Flag,
    }
    return true;
 }
-bool pkgTagSection::FindFlag(const char *Tag,unsigned long &Flags,
+bool pkgTagSection::FindFlag(StringView Tag,unsigned long &Flags,
 			     unsigned long Flag) const
 {
    const char *Start;
@@ -839,13 +843,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 +869,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 +893,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 +923,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 +947,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 +1011,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;
 

+ 28 - 5
apt-pkg/tagfile.h

@@ -27,6 +27,9 @@
 #include <string>
 #include <vector>
 #include <list>
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+#include <apt-pkg/string_view.h>
+#endif
 
 #ifndef APT_8_CLEANER_HEADERS
 #include <apt-pkg/fileutl.h>
@@ -58,19 +61,40 @@ class pkgTagSection
    inline bool operator ==(const pkgTagSection &rhs) {return Section == rhs.Section;};
    inline bool operator !=(const pkgTagSection &rhs) {return Section != rhs.Section;};
 
+#if !defined(APT_PKG_EXPOSE_STRING_VIEW) || defined(APT_COMPILING_TAGFILE_COMPAT_CC)
    bool Find(const char *Tag,const char *&Start, const char *&End) const;
    bool Find(const char *Tag,unsigned int &Pos) const;
-   std::string FindS(const char *Tag) const;
-   std::string FindRawS(const char *Tag) const;
    signed int FindI(const char *Tag,signed long Default = 0) const;
    bool FindB(const char *Tag, bool const &Default = false) const;
    unsigned long long FindULL(const char *Tag, unsigned long long const &Default = 0) const;
    bool FindFlag(const char * const Tag,uint8_t &Flags,
 		 uint8_t const Flag) const;
-   bool static FindFlag(uint8_t &Flags, uint8_t const Flag,
-				const char* const Start, const char* const Stop);
    bool FindFlag(const char *Tag,unsigned long &Flags,
 		 unsigned long Flag) const;
+   bool Exists(const char* const Tag) const;
+#endif
+   // TODO: Remove internally
+   std::string FindS(const char *Tag) const;
+   std::string FindRawS(const char *Tag) const;
+
+#ifdef APT_PKG_EXPOSE_STRING_VIEW
+   APT_HIDDEN bool Find(APT::StringView Tag,const char *&Start, const char *&End) const;
+   APT_HIDDEN bool Find(APT::StringView Tag,unsigned int &Pos) const;
+   APT_HIDDEN APT::StringView Find(APT::StringView Tag) const;
+   APT_HIDDEN APT::StringView FindRaw(APT::StringView Tag) const;
+   APT_HIDDEN signed int FindI(APT::StringView Tag,signed long Default = 0) const;
+   APT_HIDDEN bool FindB(APT::StringView, bool Default = false) const;
+   APT_HIDDEN unsigned long long FindULL(APT::StringView Tag, unsigned long long const &Default = 0) const;
+
+   APT_HIDDEN bool FindFlag(APT::StringView Tag,uint8_t &Flags,
+		 uint8_t const Flag) const;
+   APT_HIDDEN bool FindFlag(APT::StringView Tag,unsigned long &Flags,
+		 unsigned long Flag) const;
+   APT_HIDDEN bool Exists(APT::StringView Tag) const;
+#endif
+
+   bool static FindFlag(uint8_t &Flags, uint8_t const Flag,
+				const char* const Start, const char* const Stop);
    bool static FindFlag(unsigned long &Flags, unsigned long Flag,
 				const char* Start, const char* Stop);
 
@@ -102,7 +126,6 @@ class pkgTagSection
     * times, but only the last occurrence is available via Find methods.
     */
    unsigned int Count() const;
-   bool Exists(const char* const Tag) const;
 
    void Get(const char *&Start,const char *&Stop,unsigned int I) const;