Changeset 516 for trunk


Ignore:
Timestamp:
Dec 9, 2007, 8:58:54 AM (14 years ago)
Author:
Peter Johansson
Message:

adding filename translations in Configuration class. Before checking what type parsing to use, filename is translated according to rules set in config file. Default rule (as before) is to remove trailing .in from filenames. To solve the parsing I added a simple regexp function - see utility.h

Location:
trunk
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/Configuration.cc

    r515 r516  
    6565  Configuration::codon(std::string file_name) const
    6666  {
     67    if (const std::pair<std::string,std::string>* dict=dictionary(file_name))
     68      try {
     69        file_name = translate(file_name, *dict);
     70      }
     71      catch (std::runtime_error& e) {
     72        std::stringstream mess;
     73        mess << "svndigest: invalid config file: "
     74             << "expression " << dict->second << " is invalid";
     75        if (e.what()[0])
     76          mess << "because " << e.what() << " is a too large.";
     77        else
     78          mess << ".";
     79        throw std::runtime_error(mess.str());
     80      }
    6781    for (String2Codons::const_iterator i(string2codons_.begin());
    6882         i!=string2codons_.end(); ++i) {
     
    8296
    8397
     98  const std::pair<std::string,std::string>*
     99  Configuration::dictionary(std::string lhs) const
     100  {
     101    for (size_t i=0; i<dictionary_.size(); ++i)
     102      if (svndigest::equal(lhs.begin(), lhs.end(),
     103                           dictionary_[i].first.begin(),
     104                           dictionary_[i].first.end()))
     105        return &dictionary_[i];
     106    return NULL;
     107  }
     108
     109
    84110  bool Configuration::equal_false(const std::string& str) const
    85111  {
     
    108134
    109135    bool parsing_found=false;
     136    bool dictionary_found=false;
    110137    std::string line;
    111138    std::string section;
     
    178205          mess << "svndigest: invalid config file\n"
    179206               << "line: `" << line << "' is invalid.\n"
    180                << "clashes with previous given file-name-pattern: ";
     207               << "clashes with previous given file name pattern: ";
    181208          // find previous file-name-pattern
    182209          for (String2Codons::const_iterator i(string2codons_.begin());
     
    210237        }
    211238      }
     239      else if (section == "file-name-dictionary") {
     240        if (!dictionary_found) {
     241          dictionary_found=true;
     242          // clearing the default setting
     243          dictionary_.clear();
     244        }
     245       
     246        if (const std::pair<std::string, std::string>* entry=dictionary(lhs)) {
     247          std::stringstream mess;
     248          mess << "svndigest: invalid config file\n"
     249               << "line: `" << line << "' is invalid.\n"
     250               << "clashes with previous given file name pattern: "
     251               << "`" << entry->first << "'";
     252          throw std::runtime_error(mess.str());
     253        }
     254        lhs = trim(lhs);
     255        rhs = trim(rhs);
     256        if (!lhs.empty() && !rhs.empty())
     257          dictionary_.push_back(std::make_pair(lhs, rhs));
     258        else if (!lhs.empty() || !rhs.empty()) {
     259            std::stringstream mess;
     260            mess << "svndigest: invalid config file\n"
     261                 << "line: `" << line << "' is invalid.\n";
     262            throw std::runtime_error(mess.str());
     263        }
     264      }
    212265    }
    213266  }
     
    225278  {
    226279    return missing_copyright_warning_;
     280  }
     281
     282
     283  std::string
     284  Configuration::translate(const std::string& str,
     285                           const std::pair<std::string, std::string>& dic) const
     286  {
     287    assert(svndigest::equal(str.begin(), str.end(),
     288                            dic.first.begin(), dic.first.end()));
     289    std::string res;
     290    std::vector<std::string> vec;
     291    regexp(str.begin(), str.end(), dic.first.begin(), dic.first.end(), vec);
     292    for (std::string::const_iterator i(dic.second.begin());
     293         i!=dic.second.end(); ++i) {
     294      if (*i == '$') {
     295        std::stringstream ss(std::string(i, dic.second.end()));
     296        size_t n = 0;
     297        ss >> n;
     298        if (n>vec.size()){
     299          std::stringstream mess;
     300          mess << n;
     301          throw std::runtime_error(mess.str());
     302        }
     303        if (n) {
     304          res += vec[n-1];
     305          ++i;
     306          if (n>9){
     307            ++i;
     308            if (n>99)
     309              ++i;
     310          }
     311        }
     312        else
     313          throw std::runtime_error("");
     314      }
     315      else
     316        res += *i;
     317    }
     318
     319    return res;
    227320  }
    228321
  • trunk/lib/Configuration.h

    r515 r516  
    9696
    9797    void clear(void);
    98 
     98    const std::pair<std::string,std::string>* dictionary(std::string lhs) const;
    9999    bool equal_false(const std::string&) const;
    100100    bool equal_true(const std::string&) const;
    101     std::string trans_end_code(std::string) const;
    102     std::string trans_beg_code(std::string) const;
    103101    void set_default(void);
     102    /**
     103       Translate string \a str using dictionary \a dict
     104
     105       \note \a str must be equal to d.first, or behavior is unspecified.
     106
     107       \throw if a '$' character is not followed by a positive integer
     108       that is not larger than number of wildcards in dictionary \a d.
     109     */
     110    std::string translate(const std::string& str,
     111                          const std::pair<std::string, std::string>& d) const;
    104112   
    105113    static Configuration* instance_;
     
    123131  std::ostream& operator<<(std::ostream&, const Configuration&);
    124132
     133  /**
     134     If first character is '\n' replace it with "<NEWLINE>"
     135   */
     136  std::string trans_end_code(std::string);
     137
     138  /**
     139     If last character is '\n' replace it with "<NEWLINE>"
     140   */
     141  std::string trans_beg_code(std::string);
     142
    125143}} // end of namespace svndigest and namespace theplu
    126144
  • trunk/lib/Parser.cc

    r514 r516  
    4343    std::ifstream is(path.c_str());
    4444    assert(is.good());
    45     // Ignore trailing '.in' in file names
    46     if (match_end(path.rbegin(), path.rend(), ".in"))
    47       path = path.substr(0, path.size()-3);
    4845    const std::vector<std::pair<std::string, std::string> >* codon =
    4946      Configuration::instance().codon(path);
  • trunk/lib/utility.cc

    r514 r516  
    2424#include "utility.h"
    2525
     26#include <cassert>
    2627#include <cerrno>
    2728#include <cstdlib>
     
    208209
    209210
     211  bool regexp(std::string::const_iterator first1,
     212              std::string::const_iterator last1,
     213              std::string::const_iterator first2,
     214              std::string::const_iterator last2,
     215              std::vector<std::string>& vec)
     216  {
     217    if (vec.empty())
     218      vec.push_back("");
     219
     220    // first two cases when ranges are empty
     221    if (first1==last1 && first2==last2){
     222      vec.pop_back();
     223      return true;
     224    }
     225    if (first1==last1 || first2==last2)
     226      return false;
     227
     228    // then we take care of the real stuff
     229    if (*first2 == '*'){
     230      // trying '*' to consume another character
     231      vec.back().append(1, *first1);
     232      if (regexp(first1+1, last1, first2, last2, vec) )
     233        return true;
     234      assert(vec.back().size());
     235      vec.back().resize(vec.back().size()-1);
     236
     237      // stepping away from the '*'
     238      vec.push_back("");
     239      if (regexp(first1, last1, first2+1, last2, vec))
     240        return true;
     241      vec.pop_back();
     242      return false;
     243    }
     244    else if (*first2 == '?'){
     245      // eating a character
     246      vec.back() = std::string(first1, first1+1);
     247      vec.push_back("");
     248      if (regexp(first1+1, last1, first2+1, last2, vec) )
     249        return true;
     250      vec.pop_back();
     251      // ? interpreted as zero characters
     252      vec.back() = "";
     253      vec.push_back("");
     254      if (regexp(first1, last1, first2+1, last2, vec) )
     255        return true;
     256      vec.pop_back();
     257      return false;
     258    }
     259    if (*first1 != *first2)
     260      return false;
     261    return regexp(++first1, last1, ++first2, last2, vec);
     262  }
     263
     264
    210265  void replace(std::string& str, std::string old_str, std::string new_str)
    211266  {
  • trunk/lib/utility.h

    r514 r516  
    150150  ///
    151151  std::string pwd(void);
     152
     153  /**
     154     \return true if first range match second range
     155
     156     Second range may contain wildcards (such as '*' and '?'), in
     157     which case vector \a vec is filled with the corresponding strings
     158     in first range. The algorithm is greedy, i.e., wildcard * is will
     159     consume as many charcters as possible.
     160
     161     \note \a vec is supposed to be empty
     162   */
     163  bool regexp(std::string::const_iterator first1,
     164              std::string::const_iterator end1,
     165              std::string::const_iterator first2,
     166              std::string::const_iterator end2,
     167              std::vector<std::string>& vec);
    152168
    153169  /**
  • trunk/test/repo/db/current

    r513 r516  
    1 55 1l 1
     156 1l 1
  • trunk/test/utility_test.cc

    r507 r516  
    2424#include "utility.h"
    2525
     26#include <algorithm>
     27#include <iterator>
    2628#include <iostream>
    2729#include <string>
     
    2931bool test_hex(int, u_int, std::string);
    3032bool test_equal(bool, std::string, std::string);
     33bool test_regexp(bool, std::string, std::string,
     34                 const std::vector<std::string>&);
    3135
    3236int main(const int argc,const char* argv[])
     
    4347  ok &= test_equal(true,"peter", "p*");
    4448  ok &= test_equal(false,"peter", "p*j");
     49
     50  std::vector<std::string> vec;
     51  ok &= test_regexp(true,"abcde", "abcde", vec);
     52  vec.push_back("");
     53  ok &= test_regexp(true,"abcde", "abcd?e", vec);
     54  vec[0]="c";
     55  ok &= test_regexp(true,"abcde", "ab?de", vec);
     56  vec[0] = "bcd";
     57  ok &= test_regexp(true,"abcde", "a*e", vec);
     58  vec.push_back("");
     59  ok &= test_regexp(true,"abcddf", "a*d*f", vec);
     60  vec[0] = "bc";
     61  vec[1] = "ef";
     62  ok &= test_regexp(true,"abcdefg", "a*d*g", vec);
     63  vec.push_back("");
     64  ok &= test_regexp(true,"abcdefg", "a*d*?g", vec);
    4565
    4666  if (ok)
     
    6989}
    7090
     91bool test_regexp(bool ans, std::string a, std::string b,
     92                 const std::vector<std::string>& vec)
     93{
     94  using namespace theplu::svndigest;
     95  std::vector<std::string> v;
     96  bool res = regexp(a.begin(), a.end(), b.begin(), b.end(), v);
     97  if (res!=ans || v!=vec) {
     98    std::cerr << "regexp(" << a << ", " << b << ") results "
     99              << res << ". Expected " << ans << "\n"
     100              << "resulting vector:\n";
     101    std::copy(v.begin(), v.end(),
     102              std::ostream_iterator<std::string>(std::cerr, "\n"));
     103    std::cerr << "expected:\n";
     104    std::copy(vec.begin(), vec.end(),
     105              std::ostream_iterator<std::string>(std::cerr, "\n"));
     106    return false;
     107  }
     108  return true;
     109
     110}
Note: See TracChangeset for help on using the changeset viewer.