| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 | /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying   file Copyright.txt or https://cmake.org/licensing for details.  */#include "cmStringReplaceHelper.h"#include "cmMakefile.h"#include <sstream>cmStringReplaceHelper::cmStringReplaceHelper(const std::string& regex,                                             const std::string& replace_expr,                                             cmMakefile* makefile)  : RegExString(regex)  , RegularExpression(regex)  , ReplaceExpression(replace_expr)  , Makefile(makefile){  this->ParseReplaceExpression();}bool cmStringReplaceHelper::Replace(const std::string& input,                                    std::string& output){  output.clear();  // Scan through the input for all matches.  std::string::size_type base = 0;  while (this->RegularExpression.find(input.c_str() + base)) {    if (this->Makefile != nullptr) {      this->Makefile->ClearMatches();      this->Makefile->StoreMatches(this->RegularExpression);    }    auto l2 = this->RegularExpression.start();    auto r = this->RegularExpression.end();    // Concatenate the part of the input that was not matched.    output += input.substr(base, l2);    // Make sure the match had some text.    if (r - l2 == 0) {      std::ostringstream error;      error << "regex \"" << this->RegExString << "\" matched an empty string";      this->ErrorString = error.str();      return false;    }    // Concatenate the replacement for the match.    for (const auto& replacement : this->Replacements) {      if (replacement.Number < 0) {        // This is just a plain-text part of the replacement.        output += replacement.Value;      } else {        // Replace with part of the match.        auto n = replacement.Number;        auto start = this->RegularExpression.start(n);        auto end = this->RegularExpression.end(n);        auto len = input.length() - base;        if ((start != std::string::npos) && (end != std::string::npos) &&            (start <= len) && (end <= len)) {          output += input.substr(base + start, end - start);        } else {          std::ostringstream error;          error << "replace expression \"" << this->ReplaceExpression                << "\" contains an out-of-range escape for regex \""                << this->RegExString << "\"";          this->ErrorString = error.str();          return false;        }      }    }    // Move past the match.    base += r;  }  // Concatenate the text after the last match.  output += input.substr(base, input.length() - base);  return true;}void cmStringReplaceHelper::ParseReplaceExpression(){  std::string::size_type l = 0;  while (l < this->ReplaceExpression.length()) {    auto r = this->ReplaceExpression.find('\\', l);    if (r == std::string::npos) {      r = this->ReplaceExpression.length();      this->Replacements.emplace_back(        this->ReplaceExpression.substr(l, r - l));    } else {      if (r - l > 0) {        this->Replacements.emplace_back(          this->ReplaceExpression.substr(l, r - l));      }      if (r == (this->ReplaceExpression.length() - 1)) {        this->ValidReplaceExpression = false;        this->ErrorString = "replace-expression ends in a backslash";        return;      }      if ((this->ReplaceExpression[r + 1] >= '0') &&          (this->ReplaceExpression[r + 1] <= '9')) {        this->Replacements.emplace_back(this->ReplaceExpression[r + 1] - '0');      } else if (this->ReplaceExpression[r + 1] == 'n') {        this->Replacements.emplace_back("\n");      } else if (this->ReplaceExpression[r + 1] == '\\') {        this->Replacements.emplace_back("\\");      } else {        this->ValidReplaceExpression = false;        std::ostringstream error;        error << "Unknown escape \"" << this->ReplaceExpression.substr(r, 2)              << "\" in replace-expression";        this->ErrorString = error.str();        return;      }      r += 2;    }    l = r;  }}
 |