string: introduce REPEAT sub-command

This commit is contained in:
Alex Turbov
2019-04-06 17:53:58 +08:00
committed by Brad King
parent db6fdfdb05
commit 536cca60ea
12 changed files with 136 additions and 0 deletions

View File

@@ -1,9 +1,13 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#define _SCL_SECURE_NO_WARNINGS
#include "cmStringCommand.h"
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
#include <ctype.h>
#include <iterator>
#include <memory> // IWYU pragma: keep
#include <sstream>
#include <stdio.h>
@@ -13,6 +17,7 @@
#include "cmCryptoHash.h"
#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmRange.h"
#include "cmStringReplaceHelper.h"
#include "cmSystemTools.h"
@@ -79,6 +84,9 @@ bool cmStringCommand::InitialPass(std::vector<std::string> const& args,
if (subCommand == "STRIP") {
return this->HandleStripCommand(args);
}
if (subCommand == "REPEAT") {
return this->HandleRepeatCommand(args);
}
if (subCommand == "RANDOM") {
return this->HandleRandomCommand(args);
}
@@ -709,6 +717,59 @@ bool cmStringCommand::HandleStripCommand(std::vector<std::string> const& args)
return true;
}
bool cmStringCommand::HandleRepeatCommand(std::vector<std::string> const& args)
{
// `string(REPEAT "<str>" <times> OUTPUT_VARIABLE)`
enum ArgPos : std::size_t
{
SUB_COMMAND,
VALUE,
TIMES,
OUTPUT_VARIABLE,
TOTAL_ARGS
};
if (args.size() != ArgPos::TOTAL_ARGS) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
"sub-command REPEAT requires three arguments.");
return true;
}
unsigned long times;
if (!cmSystemTools::StringToULong(args[ArgPos::TIMES].c_str(), &times)) {
this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
"repeat count is not a positive number.");
return true;
}
const auto& stringValue = args[ArgPos::VALUE];
const auto& variableName = args[ArgPos::OUTPUT_VARIABLE];
const auto inStringLength = stringValue.size();
std::string result;
switch (inStringLength) {
case 0u:
// Nothing to do for zero length input strings
break;
case 1u:
// NOTE If the string to repeat consists of the only character,
// use the appropriate constructor.
result = std::string(times, stringValue[0]);
break;
default:
result = std::string(inStringLength * times, char{});
for (auto i = 0u; i < times; ++i) {
std::copy(cm::cbegin(stringValue), cm::cend(stringValue),
&result[i * inStringLength]);
}
break;
}
this->Makefile->AddDefinition(variableName, result.c_str());
return true;
}
bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args)
{
if (args.size() < 2 || args.size() == 3 || args.size() == 5) {