[Aptitude-svn-commit] r3700 - in branches/aptitude-0.3/aptitude: .
src/generic
Daniel Burrows
dburrows at costa.debian.org
Wed Jul 27 15:38:51 UTC 2005
Author: dburrows
Date: Wed Jul 27 15:38:46 2005
New Revision: 3700
Modified:
branches/aptitude-0.3/aptitude/ChangeLog
branches/aptitude-0.3/aptitude/src/generic/matchers.cc
branches/aptitude-0.3/aptitude/src/generic/matchers.h
Log:
First step towards more flexible parsing of matchers.
Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog (original)
+++ branches/aptitude-0.3/aptitude/ChangeLog Wed Jul 27 15:38:46 2005
@@ -1,3 +1,14 @@
+2005-07-27 Daniel Burrows <dburrows at debian.org>
+
+ * src/generic/matchers.cc, src/generic/matchers.h:
+
+ Change the external and internal interfaces to use iterators
+ rather than passing in a string and directly indexing into it.
+ The start iterator is modified as a side-effect, which should
+ eventually allow continuation-based parsing (i.e., just parse
+ the first thing that looks like a match term and then stop). I
+ might need to think more about just how this will work, though.
+
2005-07-26 Daniel Burrows <dburrows at debian.org>
* tests/Makefile.am, tests/test_misc.cc:
Modified: branches/aptitude-0.3/aptitude/src/generic/matchers.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/matchers.cc (original)
+++ branches/aptitude-0.3/aptitude/src/generic/matchers.cc Wed Jul 27 15:38:46 2005
@@ -1513,84 +1513,92 @@
return (pkgCache::Dep::DepType) -1;
}
-pkg_matcher *parse_condition_list(const string &s, unsigned int &loc,
+pkg_matcher *parse_condition_list(string::const_iterator &start,
+ const string::const_iterator &end,
bool match_descriptions);
// Returns a substring up to the first metacharacter, including escaped
// metacharacters (parentheses, ~, |, and !)
//
// Advances loc to the first character of 's' following the escaped string.
-std::string parse_substr(const string &s, unsigned int &loc)
+std::string parse_substr(string::const_iterator &start,
+ const string::const_iterator &end)
{
std::string rval="";
bool done=false;
do
{
- while(loc<s.size() &&
- s[loc]!='(' &&
- s[loc]!=')' &&
- s[loc]!='!' &&
- s[loc]!='~' &&
- s[loc]!='|')
+ while(start != end &&
+ *start != '(' &&
+ *start != ')' &&
+ *start != '!' &&
+ *start != '~' &&
+ *start != '|')
{
- rval+=s[loc];
- ++loc;
+ rval += *start;
+ ++start;
}
// We quit because we ran off the end of the string or saw a
// metacharacter. If the latter case and it was a tilde-escape,
// add the escaped character to the string and continue.
- if(loc<s.size()-1 && s[loc]=='~' &&
- (s[loc+1]=='(' || s[loc+1]==')' ||
- s[loc+1]=='!' || s[loc+1]=='~' ||
- s[loc+1]=='|'))
+ if(start != end && start+1 != end && *start == '~')
{
- rval+=s[loc+1];
- loc+=2;
+ const char next = *(start+1);
+
+ if(next == '(' || next == ')' ||
+ next == '!' || next == '~' ||
+ next == '|')
+ {
+ rval += next;
+ start += 2;
+ }
+ else
+ done=true;
}
- else
- done=true;
} while(!done);
return rval;
}
-pkg_matcher *parse_atom(const string &s, unsigned int &loc,
+pkg_matcher *parse_atom(string::const_iterator &start,
+ const string::const_iterator &end,
bool search_descriptions)
{
std::string substr;
- while(loc<s.size() && isspace(s[loc]))
- loc++;
+ while(start != end && isspace(*start))
+ ++start;
- while(loc<s.size() && s[loc]!='|' && s[loc]!=')')
+ while(start != end && *start != '|' && *start != ')')
{
- if(s[loc]=='!')
+ if(*start == '!')
{
- loc++;
- return new pkg_not_matcher(parse_atom(s, loc, search_descriptions));
+ ++start;
+ return new pkg_not_matcher(parse_atom(start, end,
+ search_descriptions));
}
- else if(s[loc]=='(')
+ else if(*start == '(')
// Recur into the list
{
- loc++;
- auto_ptr<pkg_matcher> lst(parse_condition_list(s, loc,
+ ++start;
+ auto_ptr<pkg_matcher> lst(parse_condition_list(start, end,
search_descriptions));
- if(!(loc<s.size() && s[loc]==')'))
+ if(!(start != end && *start == ')'))
throw CompilationException(_("Unmatched '('"));
else
{
- loc++;
+ ++start;
return lst.release();
}
}
- else if(s[loc]=='~')
+ else if(*start == '~')
{
- if(loc+1==s.size())
+ if(start + 1 == end)
{
- loc++;
+ ++start;
if(!search_descriptions)
return new pkg_name_matcher("~");
else
@@ -1604,9 +1612,12 @@
}
else
{
- unsigned int prevloc=loc;
- loc+=2;
- switch(s[prevloc+1])
+ ++start;
+ const char search_flag = *start;
+
+ ++start;
+
+ switch(search_flag)
// Nested switch statements, mmmm...
// Ok, there really is a reason here. For all of the match
// types that need a string argument, some prefix code (see
@@ -1637,9 +1648,11 @@
case 'P':
case 'C':
{
- auto_ptr<pkg_matcher> m(parse_atom(s, loc, search_descriptions));
+ auto_ptr<pkg_matcher> m(parse_atom(start,
+ end,
+ search_descriptions));
- switch(s[prevloc+1])
+ switch(search_flag)
{
case 'C':
return new pkg_dep_matcher(pkgCache::Dep::Conflicts, m.release());
@@ -1652,16 +1665,18 @@
{
bool do_provides=false;
pkgCache::Dep::DepType type=pkgCache::Dep::Depends;
- string::size_type nextloc=loc;
- while(nextloc<s.size() && isalpha(s[nextloc]))
- ++nextloc;
+ string::const_iterator nextstart = start;
+
+ while(nextstart != end && isalpha(*nextstart))
+ ++nextstart;
- if(nextloc<s.size() && s[nextloc]==':')
+ if(nextstart != end && *nextstart == ':')
{
- string tname(s, loc, nextloc-loc);
+ string tname(start, nextstart);
- loc=nextloc+1;
+ start = nextstart;
+ ++start;
if(!strcasecmp(tname.c_str(), "provides"))
do_provides=true;
@@ -1675,9 +1690,10 @@
}
}
- auto_ptr<pkg_matcher> m(parse_atom(s, loc, search_descriptions));
+ auto_ptr<pkg_matcher> m(parse_atom(start, end,
+ search_descriptions));
- switch(s[prevloc+1])
+ switch(search_flag)
{
case 'D':
if(do_provides)
@@ -1692,8 +1708,8 @@
}
}
default:
- substr=parse_substr(s, loc);
- switch(s[prevloc+1])
+ substr=parse_substr(start, end);
+ switch(search_flag)
{
case 'a':
{
@@ -1792,7 +1808,7 @@
case 'V':
return new pkg_version_matcher(substr);
default:
- throw CompilationException(_("Unknown pattern type: %c"), s[1]);
+ throw CompilationException(_("Unknown pattern type: %c"), search_flag);
}
}
}
@@ -1800,10 +1816,10 @@
else
{
if(!search_descriptions)
- return new pkg_name_matcher(parse_substr(s, loc));
+ return new pkg_name_matcher(parse_substr(start, end));
else
{
- substr=parse_substr(s, loc);
+ substr=parse_substr(start, end);
auto_ptr<pkg_matcher> name(new pkg_name_matcher(substr));
auto_ptr<pkg_matcher> desc(new pkg_description_matcher(substr));
@@ -1817,16 +1833,17 @@
throw CompilationException(_("Can't search for \"\""));
}
-pkg_matcher *parse_and_group(const string &s, unsigned int &loc,
+pkg_matcher *parse_and_group(string::const_iterator &start,
+ const string::const_iterator &end,
bool search_descriptions)
{
auto_ptr<pkg_matcher> rval(NULL);
- while(loc<s.size() && isspace(s[loc]))
- loc++;
+ while(start != end && isspace(*start))
+ ++start;
- while(loc<s.size() && s[loc]!='|' && s[loc]!=')')
+ while(start != end && *start != '|' && *start != ')')
{
- auto_ptr<pkg_matcher> atom(parse_atom(s, loc,
+ auto_ptr<pkg_matcher> atom(parse_atom(start, end,
search_descriptions));
if(rval.get()==NULL)
@@ -1834,8 +1851,8 @@
else
rval = auto_ptr<pkg_matcher>(new pkg_and_matcher(rval.release(), atom.release()));
- while(loc<s.size() && isspace(s[loc]))
- loc++;
+ while(start != end && isspace(*start))
+ ++start;
}
if(rval.get()==NULL)
@@ -1844,20 +1861,22 @@
return rval.release();
}
-pkg_matcher *parse_condition_list(const string &s, unsigned int &loc,
+pkg_matcher *parse_condition_list(string::const_iterator &start,
+ const string::const_iterator &end,
bool search_descriptions)
{
- auto_ptr<pkg_matcher> grp(parse_and_group(s, loc, search_descriptions));
+ auto_ptr<pkg_matcher> grp(parse_and_group(start, end,
+ search_descriptions));
- while(loc<s.size() && isspace(s[loc]))
- loc++;
+ while(start != end && isspace(*start))
+ ++start;
- while(loc<s.size() && s[loc]!=')')
+ while(start != end && *start != ')')
{
- if(loc<s.size() && s[loc]=='|')
+ if(start != end && *start == '|')
{
- loc++;
- auto_ptr<pkg_matcher> grp2(parse_condition_list(s, loc,
+ ++start;
+ auto_ptr<pkg_matcher> grp2(parse_condition_list(start, end,
search_descriptions));
return new pkg_or_matcher(grp.release(), grp2.release());
@@ -1866,8 +1885,8 @@
throw CompilationException(_("Badly formed expression"));
// Note that this code should never execute:
- while(loc<s.size() && isspace(s[loc]))
- loc++;
+ while(start != end && isspace(*start))
+ ++start;
}
// If there's no second element in the condition list, return its
@@ -1875,24 +1894,25 @@
return grp.release();
}
-pkg_matcher *parse_pattern(const string &s,
- bool search_descriptions, bool flag_errors)
+pkg_matcher *parse_pattern(string::const_iterator &start,
+ const string::const_iterator &end,
+ bool search_descriptions,
+ bool flag_errors,
+ bool require_full_parse)
{
- unsigned int loc=0;
-
// Just filter blank strings out immediately.
- while(loc!=s.size() && isspace(s[loc]))
- loc++;
+ while(start != end && isspace(*start))
+ ++start;
- if(loc==s.size())
+ if(start == end)
return NULL;
try
{
- auto_ptr<pkg_matcher> rval(parse_condition_list(s, loc,
+ auto_ptr<pkg_matcher> rval(parse_condition_list(start, end,
search_descriptions));
- if(loc!=s.size())
+ if(require_full_parse && start != end)
throw CompilationException(_("Unexpected ')'"));
else
return rval.release();
Modified: branches/aptitude-0.3/aptitude/src/generic/matchers.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/matchers.h (original)
+++ branches/aptitude-0.3/aptitude/src/generic/matchers.h Wed Jul 27 15:38:46 2005
@@ -23,6 +23,8 @@
#ifndef MATCHERS_H
#define MATCHERS_H
+#include <string>
+
#include <apt-pkg/pkgcache.h>
/* For the cases where you want to investigate just what you matched a
@@ -57,32 +59,49 @@
virtual ~pkg_matcher();
};
-/** Parse the given pattern, returning a matcher.
+/** Parse the given pattern, returning a matcher. start will be
+ * modified to point to the first unparsable location.
*
- * \param s the pattern to parse
+ * \param start the beginning of the range to parse
+ * \param end the end of the range to parse
* \param search_descriptions if \b true, then strings without an
* explicit pattern escape will be used to search
* both names and descriptions rather than
* names alone
* \param flag_errors if \b true, then error messages will be generated
* for incorrect patterns.
+ * \param require_full_parse if \b true, then an error will be signalled
+ * if the entire range [start,end) can't be
+ * parsed.
*
* \return the new matcher or \b NULL if an error occurs.
*/
-pkg_matcher *parse_pattern(const string &s,
+pkg_matcher *parse_pattern(std::string::const_iterator &start,
+ const std::string::const_iterator &end,
bool search_descriptions=false,
- bool flag_errors=true);
+ bool flag_errors=true,
+ bool require_full_parse=true);
+
+inline pkg_matcher *parse_pattern(const std::string &s,
+ bool search_descriptions = false,
+ bool flag_errors = true)
+{
+ std::string::const_iterator start = s.begin();
+ return parse_pattern(start, s.end(), search_descriptions, flag_errors,
+ true);
+}
+
inline bool pkg_matches(const string &s,
const pkgCache::PkgIterator &pkg,
const pkgCache::VerIterator &ver)
{
- pkg_matcher *m=parse_pattern(s);
- if(!m)
+ std::string::const_iterator start=s.begin();
+ std::auto_ptr<pkg_matcher> m(parse_pattern(start, s.end()));
+ if(m.get() == NULL)
return false;
else
{
- bool rval=m->matches(pkg, ver);
- delete m;
+ bool rval=m.get()->matches(pkg, ver);
return rval;
}
}
More information about the Aptitude-svn-commit
mailing list