mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-03 20:29:56 -06:00
Merge topic 'string-repeat'
536cca60ea string: introduce `REPEAT` sub-command
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !3239
This commit is contained in:
@@ -28,6 +28,7 @@ Synopsis
|
||||
string(`SUBSTRING`_ <string> <begin> <length> <out-var>)
|
||||
string(`STRIP`_ <string> <out-var>)
|
||||
string(`GENEX_STRIP`_ <string> <out-var>)
|
||||
string(`REPEAT`_ <string> <count> <out-var>)
|
||||
|
||||
`Comparison`_
|
||||
string(`COMPARE`_ <op> <string1> <string2> <out-var>)
|
||||
@@ -269,6 +270,14 @@ trailing spaces removed.
|
||||
Strip any :manual:`generator expressions <cmake-generator-expressions(7)>`
|
||||
from the ``input string`` and store the result in the ``output variable``.
|
||||
|
||||
.. _REPEAT:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
string(REPEAT <input string> <count> <output variable>)
|
||||
|
||||
Produce the output string as repetion of ``input string`` ``count`` times.
|
||||
|
||||
Comparison
|
||||
^^^^^^^^^^
|
||||
|
||||
|
||||
4
Help/release/dev/string-repeat.rst
Normal file
4
Help/release/dev/string-repeat.rst
Normal file
@@ -0,0 +1,4 @@
|
||||
string-repeat
|
||||
--------------
|
||||
|
||||
* The :command:`string` learned a new sub-command ``REPEAT``.
|
||||
@@ -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(), ×)) {
|
||||
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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
45
Tests/RunCMake/string/Repeat.cmake
Normal file
45
Tests/RunCMake/string/Repeat.cmake
Normal file
@@ -0,0 +1,45 @@
|
||||
string(REPEAT "q" 4 q_out)
|
||||
|
||||
if(NOT DEFINED q_out)
|
||||
message(FATAL_ERROR "q_out is not defined")
|
||||
endif()
|
||||
|
||||
if(NOT q_out STREQUAL "qqqq")
|
||||
message(FATAL_ERROR "unexpected result")
|
||||
endif()
|
||||
|
||||
string(REPEAT "1234" 0 zero_out)
|
||||
|
||||
if(NOT DEFINED zero_out)
|
||||
message(FATAL_ERROR "zero_out is not defined")
|
||||
endif()
|
||||
|
||||
if(NOT zero_out STREQUAL "")
|
||||
message(FATAL_ERROR "unexpected result")
|
||||
endif()
|
||||
|
||||
unset(zero_out)
|
||||
|
||||
string(REPEAT "" 100 zero_out)
|
||||
|
||||
if(NOT DEFINED zero_out)
|
||||
message(FATAL_ERROR "zero_out is not defined")
|
||||
endif()
|
||||
|
||||
if(NOT zero_out STREQUAL "")
|
||||
message(FATAL_ERROR "unexpected result")
|
||||
endif()
|
||||
|
||||
string(REPEAT "1" 1 one_out)
|
||||
|
||||
if(NOT one_out STREQUAL "1")
|
||||
message(FATAL_ERROR "unexpected result")
|
||||
endif()
|
||||
|
||||
unset(one_out)
|
||||
|
||||
string(REPEAT "one" 1 one_out)
|
||||
|
||||
if(NOT one_out STREQUAL "one")
|
||||
message(FATAL_ERROR "unexpected result")
|
||||
endif()
|
||||
1
Tests/RunCMake/string/RepeatNegativeCount-result.txt
Normal file
1
Tests/RunCMake/string/RepeatNegativeCount-result.txt
Normal file
@@ -0,0 +1 @@
|
||||
1
|
||||
4
Tests/RunCMake/string/RepeatNegativeCount-stderr.txt
Normal file
4
Tests/RunCMake/string/RepeatNegativeCount-stderr.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
CMake Error at RepeatNegativeCount.cmake:[0-9]+ \(string\):
|
||||
repeat count is not a positive number.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:[0-9]+ \(include\)
|
||||
1
Tests/RunCMake/string/RepeatNegativeCount.cmake
Normal file
1
Tests/RunCMake/string/RepeatNegativeCount.cmake
Normal file
@@ -0,0 +1 @@
|
||||
string(REPEAT "blah" -1 out)
|
||||
1
Tests/RunCMake/string/RepeatNoArgs-result.txt
Normal file
1
Tests/RunCMake/string/RepeatNoArgs-result.txt
Normal file
@@ -0,0 +1 @@
|
||||
1
|
||||
4
Tests/RunCMake/string/RepeatNoArgs-stderr.txt
Normal file
4
Tests/RunCMake/string/RepeatNoArgs-stderr.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
CMake Error at RepeatNoArgs.cmake:[0-9]+ \(string\):
|
||||
sub-command REPEAT requires three arguments.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:[0-9]+ \(include\)
|
||||
1
Tests/RunCMake/string/RepeatNoArgs.cmake
Normal file
1
Tests/RunCMake/string/RepeatNoArgs.cmake
Normal file
@@ -0,0 +1 @@
|
||||
string(REPEAT)
|
||||
@@ -33,3 +33,7 @@ run_cmake(UTF-16BE)
|
||||
run_cmake(UTF-16LE)
|
||||
run_cmake(UTF-32BE)
|
||||
run_cmake(UTF-32LE)
|
||||
|
||||
run_cmake(Repeat)
|
||||
run_cmake(RepeatNoArgs)
|
||||
run_cmake(RepeatNegativeCount)
|
||||
|
||||
Reference in New Issue
Block a user