summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/cmStringCommand.cxx61
-rw-r--r--Source/cmStringCommand.h1
2 files changed, 62 insertions, 0 deletions
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 252d985..998f904 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -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) {
diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h
index cbff73e..acde605 100644
--- a/Source/cmStringCommand.h
+++ b/Source/cmStringCommand.h
@@ -51,6 +51,7 @@ protected:
bool HandleConcatCommand(std::vector<std::string> const& args);
bool HandleJoinCommand(std::vector<std::string> const& args);
bool HandleStripCommand(std::vector<std::string> const& args);
+ bool HandleRepeatCommand(std::vector<std::string> const& args);
bool HandleRandomCommand(std::vector<std::string> const& args);
bool HandleFindCommand(std::vector<std::string> const& args);
bool HandleTimestampCommand(std::vector<std::string> const& args);