cmStringAlgorithms: cmIsSpace, cmTrimWhitespace, cmEscapeQuotes, cmTokenize

This adds the following functions to `cmStringAlgorithms`:

- `cmIsSpace`
- `cmTrimWhitespace` (moved from `cmSystemTools::TrimWhitespace`)
- `cmEscapeQuotes` (moved from `cmSystemTools::EscapeQuotes`)
- `cmTokenize` (moved from `cmSystemTools::tokenize` and adapted to
  accept `cm::string_view`)
This commit is contained in:
Sebastian Holtermann 2019-07-31 09:06:04 +02:00
parent 3ebd3fa51d
commit 7fbcc16dcd
23 changed files with 124 additions and 126 deletions

View File

@ -8,6 +8,7 @@
#include "cmCPackIFWRepository.h"
#include "cmCPackLog.h" // IWYU pragma: keep
#include "cmGeneratedFileStream.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
#include "cmXMLWriter.h"
@ -292,7 +293,7 @@ protected:
{
if (this->file) {
std::string content(data, data + length);
content = cmSystemTools::TrimWhitespace(content);
content = cmTrimWhitespace(content);
std::string source = this->basePath + "/" + content;
std::string destination = this->path + "/" + content;
if (!cmSystemTools::CopyFileIfDifferent(source, destination)) {

View File

@ -2,7 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCMakeToWixPath.h"
#include "cmSystemTools.h"
#include "cmStringAlgorithms.h"
#include <string>
#include <vector>
@ -29,7 +29,7 @@ std::string CMakeToWixPath(const std::string& cygpath)
return cygpath;
}
return cmSystemTools::TrimWhitespace(winpath_chars.data());
return cmTrimWhitespace(winpath_chars.data());
}
#else
std::string CMakeToWixPath(const std::string& path)

View File

@ -4,6 +4,7 @@
#include "cmCPackGenerator.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
cmWIXAccessControlList::cmWIXAccessControlList(
@ -48,8 +49,7 @@ void cmWIXAccessControlList::CreatePermissionElement(std::string const& entry)
user = user_and_domain;
}
std::vector<std::string> permissions =
cmSystemTools::tokenize(permission_string, ",");
std::vector<std::string> permissions = cmTokenize(permission_string, ",");
this->SourceWriter.BeginElement("Permission");
this->SourceWriter.AddAttribute("User", user);
@ -57,8 +57,7 @@ void cmWIXAccessControlList::CreatePermissionElement(std::string const& entry)
this->SourceWriter.AddAttribute("Domain", domain);
}
for (std::string const& permission : permissions) {
this->EmitBooleanAttribute(entry,
cmSystemTools::TrimWhitespace(permission));
this->EmitBooleanAttribute(entry, cmTrimWhitespace(permission));
}
this->SourceWriter.EndElement("Permission");
}

View File

@ -5,6 +5,7 @@
#include "cmCommandArgumentLexer.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include <iostream>
@ -58,7 +59,7 @@ const char* cmCommandArgumentParserHelper::ExpandSpecialVariable(
std::string str;
if (cmSystemTools::GetEnv(var, str)) {
if (this->EscapeQuotes) {
return this->AddString(cmSystemTools::EscapeQuotes(str));
return this->AddString(cmEscapeQuotes(str));
}
return this->AddString(str);
}
@ -68,7 +69,7 @@ const char* cmCommandArgumentParserHelper::ExpandSpecialVariable(
if (const std::string* c =
this->Makefile->GetState()->GetInitializedCacheValue(var)) {
if (this->EscapeQuotes) {
return this->AddString(cmSystemTools::EscapeQuotes(*c));
return this->AddString(cmEscapeQuotes(*c));
}
return this->AddString(*c);
}
@ -99,7 +100,7 @@ const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
}
}
if (this->EscapeQuotes && value) {
return this->AddString(cmSystemTools::EscapeQuotes(value));
return this->AddString(cmEscapeQuotes(value));
}
return this->AddString(value ? value : "");
}

View File

@ -238,7 +238,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} else if (doing == DoingLinkOptions) {
linkOptions.push_back(argv[i]);
} else if (doing == DoingLinkLibraries) {
libsToLink += "\"" + cmSystemTools::TrimWhitespace(argv[i]) + "\" ";
libsToLink += "\"" + cmTrimWhitespace(argv[i]) + "\" ";
if (cmTarget* tgt = this->Makefile->FindTargetToUse(argv[i])) {
switch (tgt->GetType()) {
case cmStateEnums::SHARED_LIBRARY:

View File

@ -21,6 +21,7 @@
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
@ -1273,11 +1274,11 @@ Json::Value Target::DumpLinkCommandFragments()
lg->GetTargetFlags(&linkLineComputer, this->Config, linkLibs,
linkLanguageFlags, linkFlags, frameworkPath, linkPath,
this->GT);
linkLanguageFlags = cmSystemTools::TrimWhitespace(linkLanguageFlags);
linkFlags = cmSystemTools::TrimWhitespace(linkFlags);
frameworkPath = cmSystemTools::TrimWhitespace(frameworkPath);
linkPath = cmSystemTools::TrimWhitespace(linkPath);
linkLibs = cmSystemTools::TrimWhitespace(linkLibs);
linkLanguageFlags = cmTrimWhitespace(linkLanguageFlags);
linkFlags = cmTrimWhitespace(linkFlags);
frameworkPath = cmTrimWhitespace(frameworkPath);
linkPath = cmTrimWhitespace(linkPath);
linkLibs = cmTrimWhitespace(linkLibs);
if (!linkLanguageFlags.empty()) {
linkFragments.append(

View File

@ -3410,8 +3410,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions(
cmSystemTools::ParseUnixCommandLine(
value.c_str() + LINKER_SHELL.length(), linkerOptions);
} else {
linkerOptions =
cmSystemTools::tokenize(value.substr(LINKER.length()), ",");
linkerOptions = cmTokenize(value.substr(LINKER.length()), ",");
}
if (linkerOptions.empty() ||

View File

@ -4,6 +4,7 @@
#include "cmMakefile.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
class cmExecutionStatus;
@ -64,7 +65,7 @@ bool cmGetFilenameComponentCommand::InitialPass(
// First assume the path to the program was specified with no
// arguments and with no quoting or escaping for spaces.
// Only bother doing this if there is non-whitespace.
if (!cmSystemTools::TrimWhitespace(filename).empty()) {
if (!cmTrimWhitespace(filename).empty()) {
result = cmSystemTools::FindProgram(filename);
}

View File

@ -383,7 +383,7 @@ void cmGlobalNinjaGenerator::WriteVariable(std::ostream& os,
}
// Do not add a variable if the value is empty.
std::string val = cmSystemTools::TrimWhitespace(value);
std::string val = cmTrimWhitespace(value);
if (val.empty()) {
return;
}
@ -528,7 +528,7 @@ bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf)
cmSystemTools::SetFatalErrorOccured();
return false;
}
this->NinjaVersion = cmSystemTools::TrimWhitespace(version);
this->NinjaVersion = cmTrimWhitespace(version);
this->CheckNinjaFeatures();
}
return true;

View File

@ -325,7 +325,7 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset(
std::string const& ts, cmMakefile* mf)
{
std::vector<std::string> const fields = cmSystemTools::tokenize(ts, ",");
std::vector<std::string> const fields = cmTokenize(ts, ",");
std::vector<std::string>::const_iterator fi = fields.begin();
if (fi == fields.end()) {
return true;

View File

@ -518,9 +518,9 @@ void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections(
const std::string::size_type posEqual = itPair.find('=');
if (posEqual != std::string::npos) {
const std::string key =
cmSystemTools::TrimWhitespace(itPair.substr(0, posEqual));
cmTrimWhitespace(itPair.substr(0, posEqual));
const std::string value =
cmSystemTools::TrimWhitespace(itPair.substr(posEqual + 1));
cmTrimWhitespace(itPair.substr(posEqual + 1));
fout << "\t\t" << key << " = " << value << "\n";
if (key == "SolutionGuid") {
addGuid = false;

View File

@ -2945,8 +2945,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup(
if (it != this->TargetGroup.end()) {
tgroup = it->second;
} else {
std::vector<std::string> tgt_folders =
cmSystemTools::tokenize(target, "/");
std::vector<std::string> tgt_folders = cmTokenize(target, "/");
std::string curr_tgt_folder;
for (std::vector<std::string>::size_type i = 0; i < tgt_folders.size();
i++) {
@ -2980,8 +2979,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup(
if (sg->GetFullName() != sg->GetName()) {
std::string curr_folder = target;
curr_folder += "/";
for (auto const& folder :
cmSystemTools::tokenize(sg->GetFullName(), "\\")) {
for (auto const& folder : cmTokenize(sg->GetFullName(), "\\")) {
curr_folder += folder;
std::map<std::string, cmXCodeObject*>::iterator i_folder =
this->GroupNameMap.find(curr_folder);

View File

@ -20,6 +20,7 @@
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTest.h"
@ -541,19 +542,19 @@ static Json::Value DumpTarget(cmGeneratorTarget* target,
lg->GetTargetFlags(&linkLineComputer, config, linkLibs, linkLanguageFlags,
linkFlags, frameworkPath, linkPath, target);
linkLibs = cmSystemTools::TrimWhitespace(linkLibs);
linkFlags = cmSystemTools::TrimWhitespace(linkFlags);
linkLanguageFlags = cmSystemTools::TrimWhitespace(linkLanguageFlags);
frameworkPath = cmSystemTools::TrimWhitespace(frameworkPath);
linkPath = cmSystemTools::TrimWhitespace(linkPath);
linkLibs = cmTrimWhitespace(linkLibs);
linkFlags = cmTrimWhitespace(linkFlags);
linkLanguageFlags = cmTrimWhitespace(linkLanguageFlags);
frameworkPath = cmTrimWhitespace(frameworkPath);
linkPath = cmTrimWhitespace(linkPath);
if (!cmSystemTools::TrimWhitespace(linkLibs).empty()) {
if (!cmTrimWhitespace(linkLibs).empty()) {
result[kLINK_LIBRARIES_KEY] = linkLibs;
}
if (!cmSystemTools::TrimWhitespace(linkFlags).empty()) {
if (!cmTrimWhitespace(linkFlags).empty()) {
result[kLINK_FLAGS_KEY] = linkFlags;
}
if (!cmSystemTools::TrimWhitespace(linkLanguageFlags).empty()) {
if (!cmTrimWhitespace(linkLanguageFlags).empty()) {
result[kLINK_LANGUAGE_FLAGS_KEY] = linkLanguageFlags;
}
if (!frameworkPath.empty()) {

View File

@ -855,7 +855,7 @@ bool cmListCommand::HandleTransformCommand(
{ "STRIP", 0,
[&command](const std::string& s) -> std::string {
if (command.Selector->InSelection(s)) {
return cmSystemTools::TrimWhitespace(s);
return cmTrimWhitespace(s);
}
return s;

View File

@ -2166,8 +2166,7 @@ cmSourceGroup* cmMakefile::GetOrCreateSourceGroup(const std::string& name)
if (delimiter == nullptr) {
delimiter = "\\";
}
return this->GetOrCreateSourceGroup(
cmSystemTools::tokenize(name, delimiter));
return this->GetOrCreateSourceGroup(cmTokenize(name, delimiter));
}
/**
@ -2659,7 +2658,7 @@ MessageType cmMakefile::ExpandVariablesInStringOld(
if (const char* val = this->GetDefinition(var)) {
// Store the value in the output escaping as requested.
if (escapeQuotes) {
source.append(cmSystemTools::EscapeQuotes(val));
source.append(cmEscapeQuotes(val));
} else {
source.append(val);
}
@ -2823,7 +2822,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew(
// Get the string we're meant to append to.
if (value) {
if (escapeQuotes) {
varresult = cmSystemTools::EscapeQuotes(value);
varresult = cmEscapeQuotes(value);
} else {
varresult = value;
}
@ -2949,7 +2948,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew(
}
if (escapeQuotes) {
varresult = cmSystemTools::EscapeQuotes(varresult);
varresult = cmEscapeQuotes(varresult);
}
// Skip over the variable.
result.append(last, in - last);

View File

@ -21,7 +21,7 @@ const std::string kSourceGroupOptionName = "<sg_name>";
std::vector<std::string> tokenizePath(const std::string& path)
{
return cmSystemTools::tokenize(path, "\\/");
return cmTokenize(path, "\\/");
}
std::string getFullFilePath(const std::string& currentPath,

View File

@ -5,6 +5,59 @@
#include <algorithm>
#include <cstdio>
std::string cmTrimWhitespace(cm::string_view str)
{
auto start = str.begin();
while (start != str.end() && cmIsSpace(*start)) {
++start;
}
if (start == str.end()) {
return std::string();
}
auto stop = str.end() - 1;
while (cmIsSpace(*stop)) {
--stop;
}
return std::string(start, stop + 1);
}
std::string cmEscapeQuotes(cm::string_view str)
{
std::string result;
result.reserve(str.size());
for (const char ch : str) {
if (ch == '"') {
result += '\\';
}
result += ch;
}
return result;
}
std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep)
{
std::vector<std::string> tokens;
cm::string_view::size_type tokend = 0;
do {
cm::string_view::size_type tokstart = str.find_first_not_of(sep, tokend);
if (tokstart == cm::string_view::npos) {
break; // no more tokens
}
tokend = str.find_first_of(sep, tokstart);
if (tokend == cm::string_view::npos) {
tokens.emplace_back(str.substr(tokstart));
} else {
tokens.emplace_back(str.substr(tokstart, tokend - tokstart));
}
} while (tokend != cm::string_view::npos);
if (tokens.empty()) {
tokens.emplace_back();
}
return tokens;
}
namespace {
template <std::size_t N, typename T>
inline void MakeDigits(cm::string_view& view, char (&digits)[N],

View File

@ -7,6 +7,7 @@
#include "cmRange.h"
#include "cm_string_view.hxx"
#include <cctype>
#include <initializer_list>
#include <sstream>
#include <string.h>
@ -31,6 +32,18 @@ private:
std::string const Test_;
};
/** Returns true if the character @a ch is a whitespace character. **/
inline bool cmIsSpace(char ch)
{
return ((ch & 0x80) == 0) && std::isspace(ch);
}
/** Returns a string that has whitespace removed from the start and the end. */
std::string cmTrimWhitespace(cm::string_view str);
/** Escape quotes in a string. */
std::string cmEscapeQuotes(cm::string_view str);
/** Joins elements of a range with separator into a single string. */
template <typename Range>
std::string cmJoin(Range const& rng, cm::string_view separator)
@ -49,6 +62,9 @@ std::string cmJoin(Range const& rng, cm::string_view separator)
return os.str();
}
/** Extract tokens that are separated by any of the characters in @a sep. */
std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep);
/** Concatenate string pieces into a single string. */
std::string cmCatViews(std::initializer_list<cm::string_view> views);

View File

@ -84,11 +84,6 @@ cmSystemTools::OutputCallback s_StdoutCallback;
} // namespace
static bool cm_isspace(char c)
{
return ((c & 0x80) == 0) && isspace(c);
}
#if !defined(HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE)
// For GetEnvironmentVariables
# if defined(_WIN32)
@ -177,19 +172,6 @@ void cmSystemTools::ExpandRegistryValues(std::string& source,
}
#endif
std::string cmSystemTools::EscapeQuotes(cm::string_view str)
{
std::string result;
result.reserve(str.size());
for (const char ch : str) {
if (ch == '"') {
result += '\\';
}
result += ch;
}
return result;
}
std::string cmSystemTools::HelpFileName(cm::string_view str)
{
std::string name(str);
@ -198,22 +180,6 @@ std::string cmSystemTools::HelpFileName(cm::string_view str)
return name;
}
std::string cmSystemTools::TrimWhitespace(cm::string_view str)
{
auto start = str.begin();
while (start != str.end() && cm_isspace(*start)) {
++start;
}
if (start == str.end()) {
return std::string();
}
auto stop = str.end() - 1;
while (cm_isspace(*stop)) {
--stop;
}
return std::string(start, stop + 1);
}
void cmSystemTools::Error(const std::string& m)
{
std::string message = "CMake Error: " + m;
@ -396,7 +362,7 @@ void cmSystemTools::ParseWindowsCommandLine(const char* command,
} else {
arg.append(backslashes, '\\');
backslashes = 0;
if (cm_isspace(*c)) {
if (cmIsSpace(*c)) {
if (in_quotes) {
arg.append(1, *c);
} else if (in_argument) {
@ -2882,31 +2848,6 @@ bool cmSystemTools::RepeatedRemoveDirectory(const std::string& dir)
return false;
}
std::vector<std::string> cmSystemTools::tokenize(const std::string& str,
const std::string& sep)
{
std::vector<std::string> tokens;
std::string::size_type tokend = 0;
do {
std::string::size_type tokstart = str.find_first_not_of(sep, tokend);
if (tokstart == std::string::npos) {
break; // no more tokens
}
tokend = str.find_first_of(sep, tokstart);
if (tokend == std::string::npos) {
tokens.push_back(str.substr(tokstart));
} else {
tokens.push_back(str.substr(tokstart, tokend - tokstart));
}
} while (tokend != std::string::npos);
if (tokens.empty()) {
tokens.emplace_back();
}
return tokens;
}
bool cmSystemTools::StringToLong(const char* str, long* value)
{
errno = 0;

View File

@ -77,17 +77,9 @@ public:
static void ExpandRegistryValues(std::string& source,
KeyWOW64 view = KeyWOW64_Default);
//! Escape quotes in a string.
static std::string EscapeQuotes(cm::string_view str);
/** Map help document name to file name. */
static std::string HelpFileName(cm::string_view);
/**
* Returns a string that has whitespace removed from the start and the end.
*/
static std::string TrimWhitespace(cm::string_view str);
using MessageCallback = std::function<void(const std::string&, const char*)>;
/**
* Set the function used by GUIs to display error messages
@ -508,10 +500,6 @@ public:
/** Remove a directory; repeat a few times in case of locked files. */
static bool RepeatedRemoveDirectory(const std::string& dir);
/** Tokenize a string */
static std::vector<std::string> tokenize(const std::string& str,
const std::string& sep);
/** Convert string to long. Expected that the whole string is an integer */
static bool StringToLong(const char* str, long* value);
static bool StringToULong(const char* str, unsigned long* value);

View File

@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVSSetupHelper.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmsys/Encoding.hxx"
#include "cmsys/FStream.hxx"
@ -195,7 +196,7 @@ bool cmVSSetupAPIHelper::GetVSInstanceInfo(
if (!fin || !cmSystemTools::GetLineFromStream(fin, vcToolsVersion)) {
return false;
}
vcToolsVersion = cmSystemTools::TrimWhitespace(vcToolsVersion);
vcToolsVersion = cmTrimWhitespace(vcToolsVersion);
std::string const vcToolsDir = vcRoot + "/VC/Tools/MSVC/" + vcToolsVersion;
if (!cmSystemTools::FileIsDirectory(vcToolsDir)) {
return false;

View File

@ -193,7 +193,7 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
std::string arch_name = arch[0];
std::vector<std::string> codes;
if (!code.empty()) {
codes = cmSystemTools::tokenize(code[0], ",");
codes = cmTokenize(code[0], ",");
}
if (codes.empty()) {
codes.push_back(arch_name);
@ -220,7 +220,7 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
cmSystemTools::ReplaceString(entry, "]", "");
cmSystemTools::ReplaceString(entry, "\"", "");
std::vector<std::string> codes = cmSystemTools::tokenize(entry, ",");
std::vector<std::string> codes = cmTokenize(entry, ",");
if (codes.size() >= 2) {
auto gencode_arch = cm::cbegin(codes);
for (auto ci = gencode_arch + 1; ci != cm::cend(codes); ++ci) {

View File

@ -463,7 +463,7 @@ bool cmVisualStudioSlnParser::ParseImpl(std::istream& input, cmSlnData& output,
if (!this->ParseBOM(input, line, state))
return false;
do {
line = cmSystemTools::TrimWhitespace(line);
line = cmTrimWhitespace(line);
if (line.empty())
continue;
ParsedLine parsedLine;
@ -579,9 +579,9 @@ bool cmVisualStudioSlnParser::ParseKeyValuePair(const std::string& line,
return true;
}
const std::string& key = line.substr(0, idxEqualSign);
parsedLine.SetTag(cmSystemTools::TrimWhitespace(key));
parsedLine.SetTag(cmTrimWhitespace(key));
const std::string& value = line.substr(idxEqualSign + 1);
parsedLine.AddValue(cmSystemTools::TrimWhitespace(value));
parsedLine.AddValue(cmTrimWhitespace(value));
return true;
}
@ -590,18 +590,17 @@ bool cmVisualStudioSlnParser::ParseTag(const std::string& fullTag,
{
size_t idxLeftParen = fullTag.find('(');
if (idxLeftParen == fullTag.npos) {
parsedLine.SetTag(cmSystemTools::TrimWhitespace(fullTag));
parsedLine.SetTag(cmTrimWhitespace(fullTag));
return true;
}
parsedLine.SetTag(
cmSystemTools::TrimWhitespace(fullTag.substr(0, idxLeftParen)));
parsedLine.SetTag(cmTrimWhitespace(fullTag.substr(0, idxLeftParen)));
size_t idxRightParen = fullTag.rfind(')');
if (idxRightParen == fullTag.npos) {
this->LastResult.SetError(ResultErrorInputStructure,
state.GetCurrentLine());
return false;
}
const std::string& arg = cmSystemTools::TrimWhitespace(
const std::string& arg = cmTrimWhitespace(
fullTag.substr(idxLeftParen + 1, idxRightParen - idxLeftParen - 1));
if (arg.front() == '"') {
if (arg.back() != '"') {
@ -618,7 +617,7 @@ bool cmVisualStudioSlnParser::ParseTag(const std::string& fullTag,
bool cmVisualStudioSlnParser::ParseValue(const std::string& value,
ParsedLine& parsedLine)
{
const std::string& trimmed = cmSystemTools::TrimWhitespace(value);
const std::string& trimmed = cmTrimWhitespace(value);
if (trimmed.empty())
parsedLine.AddValue(trimmed);
else if (trimmed.front() == '"' && trimmed.back() == '"')