From 3f8d73282cb6cc48c20b6d19ac0448df0cc950d9 Mon Sep 17 00:00:00 2001 From: Angus Leeming Date: Thu, 7 Nov 2002 15:24:06 +0000 Subject: [PATCH] * Add RegEx to the compiled boost files. * clean-up the search code in biblio.C. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@5595 a592a061-630c-0410-9148-cb99ea01b6c8 --- boost/ChangeLog | 4 + boost/libs/regex/src/Makefile.am | 4 +- src/frontends/controllers/ChangeLog | 6 ++ src/frontends/controllers/biblio.C | 134 +++++++++++++--------------- 4 files changed, 76 insertions(+), 72 deletions(-) diff --git a/boost/ChangeLog b/boost/ChangeLog index 1db2f1a0d3..b8c82e8bfb 100644 --- a/boost/ChangeLog +++ b/boost/ChangeLog @@ -1,3 +1,7 @@ +2002-11-07 Angus Leeming + + * libs/regex/src/Makefile.am: add cregex.cpp and fileiter.cpp + 2002-10-15 Lars Gullik Bjønnes * update boost to version 1.29.0. diff --git a/boost/libs/regex/src/Makefile.am b/boost/libs/regex/src/Makefile.am index 417d8a7abc..37c388ccc4 100644 --- a/boost/libs/regex/src/Makefile.am +++ b/boost/libs/regex/src/Makefile.am @@ -8,14 +8,14 @@ libboostregex_la_SOURCES = \ cpp_regex_traits.cpp \ c_regex_traits_common.cpp \ c_regex_traits.cpp \ + cregex.cpp \ + fileiter.cpp \ instances.cpp \ primary_transform.hpp \ regex.cpp \ w32_regex_traits.cpp \ regex_synch.cpp -# cregex.cpp \ -# fileiter.cpp \ # posix_api.cpp \ # wide_posix_api.cpp \ # regex_debug.cpp diff --git a/src/frontends/controllers/ChangeLog b/src/frontends/controllers/ChangeLog index 514d294dd8..bc42eb632a 100644 --- a/src/frontends/controllers/ChangeLog +++ b/src/frontends/controllers/ChangeLog @@ -1,3 +1,9 @@ +2002-11-06 Angus Leeming + + * biblio.C (searchKeys and helper functions): rewritten entirely + using the STL. Boost::regex searching now works as the old 1.2 code + did. + 2002-11-06 Angus Leeming * biblio.C: clean-up of the code. No change in functionality. diff --git a/src/frontends/controllers/biblio.C b/src/frontends/controllers/biblio.C index 99d643b5c1..01f1d07e65 100644 --- a/src/frontends/controllers/biblio.C +++ b/src/frontends/controllers/biblio.C @@ -150,7 +150,7 @@ struct compareNoCase: public std::binary_function return compare_ascii_no_case(s1, s2) < 0; } }; - + } // namespace anon @@ -238,81 +238,56 @@ string const getInfo(InfoMap const & map, string const & key) namespace { -// The functions doing the dirty work for the search. -vector::const_iterator -simpleSearch(InfoMap const & theMap, - vector const & keys, - string const & expr, - vector::const_iterator start, - Direction dir, - bool caseSensitive) +// Escape special chars. +// All characters are literals except: .|*?+(){}[]^$\ +// These characters are literals when preceded by a "\", which is done here +string const escape_special_chars(string const & expr) { - string tmp = expr; - if (!caseSensitive) - tmp = lowercase(tmp); - - vector searchwords = getVectorFromString(tmp, " "); - - // Loop over all keys from start... - for (vector::const_iterator it = start; - // End condition is direction-dependent. - (dir == FORWARD) ? (it=keys.begin()); - // increment is direction-dependent. - (dir == FORWARD) ? (++it) : (--it)) { - - string data = (*it); - InfoMap::const_iterator info = theMap.find(*it); - if (info != theMap.end()) - data += " " + info->second; - if (!caseSensitive) - data = lowercase(data); - - bool found = true; - - // Loop over all search words... - for (vector::const_iterator sit = searchwords.begin(); - sit != searchwords.end(); ++sit) { - if (data.find(*sit) == string::npos) { - found = false; - break; - } - } + // Search for all chars .|*?+(){}[]^$\ + // Note that they must be escaped in the RE. + boost::RegEx reg("[\\.\\|\\*\\?\\+\\(\\)\\{\\}\\[\\]\\^\\$\\\\]"); - if (found) return it; - } + // $& is a perl-like expression that expands to all of the current match + // The '$' must be prefixed with the escape character '\' for + // boost to treat it as a literal. + // Thus, to prefix a matched expression with '\', we use: + string const fmt("\\\\$&"); - return keys.end(); + return reg.Merge(expr, fmt); } -vector::const_iterator -regexSearch(InfoMap const & theMap, - vector const & keys, - string const & expr, - vector::const_iterator start, - Direction dir) +// A functor for use with std::find_if, used to ascertain whether a +// data entry matches the required regex_ +struct RegexMatch { - boost::regex reg(STRCONV(expr)); - - for (vector::const_iterator it = start; - // End condition is direction-dependent. - (dir == FORWARD) ? (it < keys.end()) : (it >= keys.begin()); - // increment is direction-dependent. - (dir == FORWARD) ? (++it) : (--it)) { - - string data = (*it); - InfoMap::const_iterator info = theMap.find(*it); - if (info != theMap.end()) + // re and icase are used to construct an instance of boost::RegEx. + // if icase is true, then matching is insensitive to case + RegexMatch(InfoMap const & m, string const & re, bool icase) + : map_(m), regex_(re, icase) {} + + bool operator()(string const & key) { + if (!validRE()) + return false; + + // the data searched is the key + its associated BibTeX/biblio + // fields + string data = key; + InfoMap::const_iterator info = map_.find(key); + if (info != map_.end()) data += " " + info->second; - if (boost::regex_match(STRCONV(data), reg)) { - return it; - } + // Attempts to find a match for the current RE + // somewhere in data. + return regex_.Search(data); } - return keys.end(); -} + bool validRE() const { return regex_.error_code() == 0; } +private: + InfoMap const map_; + boost::RegEx regex_; +}; } // namespace anon @@ -320,7 +295,7 @@ regexSearch(InfoMap const & theMap, vector::const_iterator searchKeys(InfoMap const & theMap, vector const & keys, - string const & expr, + string const & search_expr, vector::const_iterator start, Search type, Direction dir, @@ -330,15 +305,34 @@ searchKeys(InfoMap const & theMap, if (start < keys.begin() || start >= keys.end()) return keys.end(); - string search_expr = trim(expr); - if (search_expr.empty()) + string expr = trim(search_expr); + if (expr.empty()) return keys.end(); if (type == SIMPLE) - return simpleSearch(theMap, keys, search_expr, start, dir, - caseSensitive); + // We must escape special chars in the search_expr so that + // it is treated as a simple string by boost::regex. + expr = escape_special_chars(expr); - return regexSearch(theMap, keys, search_expr, start, dir); + // Build the functor that will be passed to find_if. + RegexMatch const match(theMap, expr, !caseSensitive); + if (!match.validRE()) + return keys.end(); + + // Search the vector of 'keys' from 'start' for one that matches the + // predicate 'match'. Searching can be forward or backward from start. + if (dir == FORWARD) + return std::find_if(start, keys.end(), match); + + vector::const_reverse_iterator rit(start); + vector::const_reverse_iterator rend = keys.rend(); + rit = std::find_if(rit, rend, match); + + if (rit == rend) + return keys.end(); + // This is correct and always safe. + // (See Meyer's Effective STL, Item 28.) + return (++rit).base(); } -- 2.39.2