summaryrefslogtreecommitdiffstats
path: root/Source/cmStringCommand.cxx
diff options
context:
space:
mode:
authorAlex Turbov <i.zaufi@gmail.com>2019-04-06 09:53:58 (GMT)
committerBrad King <brad.king@kitware.com>2019-04-15 15:06:06 (GMT)
commit536cca60ea1c037d751b03bf5da8385783856000 (patch)
tree5b3e22733a4ae2f729a3e358175ee5b69b7a5d6e /Source/cmStringCommand.cxx
parentdb6fdfdb053a372382ff8eadad9bfa47c1a3b4bc (diff)
downloadCMake-536cca60ea1c037d751b03bf5da8385783856000.zip
CMake-536cca60ea1c037d751b03bf5da8385783856000.tar.gz
CMake-536cca60ea1c037d751b03bf5da8385783856000.tar.bz2
string: introduce `REPEAT` sub-command
Diffstat (limited to 'Source/cmStringCommand.cxx')
-rw-r--r--Source/cmStringCommand.cxx61
1 files changed, 61 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) {