]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/contrib/configuration.cc
merged from lp:~donkult/apt/experimental
[apt.git] / apt-pkg / contrib / configuration.cc
index 8e3b84499c15366f1c24f89becd9873b97332c38..0f7b37ee9964d0592b09806da07fdf50a44fc5d3 100644 (file)
    ##################################################################### */
                                                                        /*}}}*/
 // Include files                                                       /*{{{*/
+#include <config.h>
+
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/fileutl.h>
-#include <apti18n.h>
 
 #include <vector>
 #include <fstream>
 #include <iostream>
 
+#include <apti18n.h>
+
 using namespace std;
                                                                        /*}}}*/
 
@@ -79,7 +82,7 @@ Configuration::~Configuration()
 /* This will lookup a single item by name below another item. It is a 
    helper function for the main lookup function */
 Configuration::Item *Configuration::Lookup(Item *Head,const char *S,
-                                          unsigned long Len,bool Create)
+                                          unsigned long const &Len,bool const &Create)
 {
    int Res = 1;
    Item *I = Head->Child;
@@ -112,7 +115,7 @@ Configuration::Item *Configuration::Lookup(Item *Head,const char *S,
 // ---------------------------------------------------------------------
 /* This performs a fully scoped lookup of a given name, possibly creating
    new items */
-Configuration::Item *Configuration::Lookup(const char *Name,bool Create)
+Configuration::Item *Configuration::Lookup(const char *Name,bool const &Create)
 {
    if (Name == 0)
       return Root->Child;
@@ -239,7 +242,7 @@ vector<string> Configuration::FindVector(const char *Name) const
 // Configuration::FindI - Find an integer value                                /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-int Configuration::FindI(const char *Name,int Default) const
+int Configuration::FindI(const char *Name,int const &Default) const
 {
    const Item *Itm = Lookup(Name);
    if (Itm == 0 || Itm->Value.empty() == true)
@@ -256,7 +259,7 @@ int Configuration::FindI(const char *Name,int Default) const
 // Configuration::FindB - Find a boolean type                          /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool Configuration::FindB(const char *Name,bool Default) const
+bool Configuration::FindB(const char *Name,bool const &Default) const
 {
    const Item *Itm = Lookup(Name);
    if (Itm == 0 || Itm->Value.empty() == true)
@@ -318,6 +321,19 @@ void Configuration::CndSet(const char *Name,const string &Value)
       Itm->Value = Value;
 }
                                                                        /*}}}*/
+// Configuration::Set - Set an integer value                           /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void Configuration::CndSet(const char *Name,int const Value)
+{
+   Item *Itm = Lookup(Name,true);
+   if (Itm == 0 || Itm->Value.empty() == false)
+      return;
+   char S[300];
+   snprintf(S,sizeof(S),"%i",Value);
+   Itm->Value = S;
+}
+                                                                       /*}}}*/
 // Configuration::Set - Set a value                                    /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -332,7 +348,7 @@ void Configuration::Set(const char *Name,const string &Value)
 // Configuration::Set - Set an integer value                           /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void Configuration::Set(const char *Name,int Value)
+void Configuration::Set(const char *Name,int const &Value)
 {
    Item *Itm = Lookup(Name,true);
    if (Itm == 0)
@@ -345,7 +361,7 @@ void Configuration::Set(const char *Name,int Value)
 // Configuration::Clear - Clear an single value from a list            /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void Configuration::Clear(const string Name, int Value)
+void Configuration::Clear(string const &Name, int const &Value)
 {
    char S[300];
    snprintf(S,sizeof(S),"%i",Value);
@@ -355,7 +371,7 @@ void Configuration::Clear(const string Name, int Value)
 // Configuration::Clear - Clear an single value from a list            /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void Configuration::Clear(const string Name, string Value)
+void Configuration::Clear(string const &Name, string const &Value)
 {
    Item *Top = Lookup(Name.c_str(),false);
    if (Top == 0 || Top->Child == 0)
@@ -386,7 +402,7 @@ void Configuration::Clear(const string Name, string Value)
 // Configuration::Clear - Clear an entire tree                         /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void Configuration::Clear(string Name)
+void Configuration::Clear(string const &Name)
 {
    Item *Top = Lookup(Name.c_str(),false);
    if (Top == 0) 
@@ -501,8 +517,8 @@ string Configuration::Item::FullTag(const Item *Stop) const
    sections like 'zone "foo.org" { .. };' This causes each section to be
    added in with a tag like "zone::foo.org" instead of being split 
    tag/value. AsSectional enables Sectional parsing.*/
-bool ReadConfigFile(Configuration &Conf,const string &FName,bool AsSectional,
-                   unsigned Depth)
+bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectional,
+                   unsigned const &Depth)
 {   
    // Open the stream for reading
    ifstream F(FName.c_str(),ios::in); 
@@ -659,9 +675,9 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool AsSectional,
            // Put the last fragment into the buffer
            std::string::const_iterator NonWhitespaceStart = Start;
            std::string::const_iterator NonWhitespaceStop = I;
-           for (; NonWhitespaceStart != I && isspace(*NonWhitespaceStart) != 0; NonWhitespaceStart++)
+           for (; NonWhitespaceStart != I && isspace(*NonWhitespaceStart) != 0; ++NonWhitespaceStart)
              ;
-           for (; NonWhitespaceStop != NonWhitespaceStart && isspace(NonWhitespaceStop[-1]) != 0; NonWhitespaceStop--)
+           for (; NonWhitespaceStop != NonWhitespaceStart && isspace(NonWhitespaceStop[-1]) != 0; --NonWhitespaceStop)
              ;
            if (LineBuffer.empty() == false && NonWhitespaceStop - NonWhitespaceStart != 0)
               LineBuffer += ' ';
@@ -773,6 +789,8 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool AsSectional,
               else
                  return _error->Error(_("Syntax error %s:%u: Unsupported directive '%s'"),FName.c_str(),CurLine,Tag.c_str());
            }
+           else if (Tag.empty() == true && NoWord == false && Word == "#clear")
+              return _error->Error(_("Syntax error %s:%u: clear directive requires an option tree as argument"),FName.c_str(),CurLine);
            else
            {
               // Set the item in the configuration class
@@ -830,14 +848,65 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool AsSectional,
 // ---------------------------------------------------------------------
 /* */
 bool ReadConfigDir(Configuration &Conf,const string &Dir,
-                  bool AsSectional, unsigned Depth)
+                  bool const &AsSectional, unsigned const &Depth)
 {
    vector<string> const List = GetListOfFilesInDir(Dir, "conf", true, true);
 
    // Read the files
-   for (vector<string>::const_iterator I = List.begin(); I != List.end(); I++)
+   for (vector<string>::const_iterator I = List.begin(); I != List.end(); ++I)
       if (ReadConfigFile(Conf,*I,AsSectional,Depth) == false)
         return false;
    return true;
 }
                                                                        /*}}}*/
+// MatchAgainstConfig Constructor                                      /*{{{*/
+Configuration::MatchAgainstConfig::MatchAgainstConfig(char const * Config)
+{
+   std::vector<std::string> const strings = _config->FindVector(Config);
+   for (std::vector<std::string>::const_iterator s = strings.begin();
+       s != strings.end(); ++s)
+   {
+      regex_t *p = new regex_t;
+      if (regcomp(p, s->c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB) == 0)
+        patterns.push_back(p);
+      else
+      {
+        regfree(p);
+        delete p;
+        clearPatterns();
+        _error->Warning("Regex compilation error for '%s' in configuration option '%s'",
+                               s->c_str(), Config);
+        return;
+      }
+   }
+   if (strings.size() == 0)
+      patterns.push_back(NULL);
+}
+                                                                       /*}}}*/
+// MatchAgainstConfig Destructor                                       /*{{{*/
+Configuration::MatchAgainstConfig::~MatchAgainstConfig()
+{
+   clearPatterns();
+}
+void Configuration::MatchAgainstConfig::clearPatterns()
+{
+   for(std::vector<regex_t *>::const_iterator p = patterns.begin();
+       p != patterns.end(); ++p)
+   {
+      if (*p == NULL) continue;
+      regfree(*p);
+      delete *p;
+   }
+}
+                                                                       /*}}}*/
+// MatchAgainstConfig::Match - returns true if a pattern matches       /*{{{*/
+bool Configuration::MatchAgainstConfig::Match(char const * str) const
+{
+   for(std::vector<regex_t *>::const_iterator p = patterns.begin();
+       p != patterns.end(); ++p)
+      if (*p != NULL && regexec(*p, str, 0, 0, 0) == 0)
+        return true;
+
+   return false;
+}
+                                                                       /*}}}*/