Implementing Expression::eval() function for the various kinds of Expression classes turns out to be a breeze, using the equal (stl) algorithm which determines that one vector is a prefix of another. Here is the code for PathExpression::eval() to illustrate the point:
bool PathExpression::eval(const LogRecord& r) const { const Path& p(r.path()); if (p.size() < path_.size()) // if r's path is shorter, it cannot match path_ return false; // It's safe to call equal() because p.size >= path_.size(). return equal(path_.begin(), path_.end(), p.begin()); }
When testing, this did not work at first. It turned out that Path::parse(const string&) did not remove leading blanks in the string, which yielded a first component string like " "
, consisting of spaces only. Since equal() compares the components of the underlying Path vectors, it immediately failed. So we had to put some trimming code (removing leading and trailing white space) somewhere: either in Path::parse() or in Configuration::parse_expression(). We prefer the latter because of performance reasons: this way, the trimming is only called when it may be useful. The condition that Path::parse() expects a trimmed string was added to the documentation in the header file. A similar problem and solution was adopted for Domain::parse().
At this stage, we have a fully functional implementation, excluding bugs or non-implemented requirements. So far, the line count for the program is about 1200 lines (excluding the code for Date.h, date.C and getdate.c, which came from elsewhere), making it a small program.
In the next stage, we will check the requirements again and run tests to verify that they are satisfied.