mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-09 23:59:53 -05:00
introduce cm::CMakeString class as helper for string() command
This class will be used, as helper for: * string() command * future $<STRING> generator expression
This commit is contained in:
@@ -135,6 +135,8 @@ add_library(
|
||||
cmCMakePresetsGraphReadJSONPackagePresets.cxx
|
||||
cmCMakePresetsGraphReadJSONTestPresets.cxx
|
||||
cmCMakePresetsGraphReadJSONWorkflowPresets.cxx
|
||||
cmCMakeString.hxx
|
||||
cmCMakeString.cxx
|
||||
cmCommandLineArgument.h
|
||||
cmCommonTargetGenerator.cxx
|
||||
cmCommonTargetGenerator.h
|
||||
|
||||
@@ -0,0 +1,326 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include "cmCMakeString.hxx"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
|
||||
#include "cmCryptoHash.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmPolicies.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmStringReplaceHelper.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTimestamp.h"
|
||||
#include "cmUuid.h"
|
||||
|
||||
namespace cm {
|
||||
bool CMakeString::Compare(CompOperator op, cm::string_view other)
|
||||
{
|
||||
switch (op) {
|
||||
case CompOperator::EQUAL:
|
||||
return this->String_ == other;
|
||||
case CompOperator::LESS:
|
||||
return this->String_ < other;
|
||||
case CompOperator::LESS_EQUAL:
|
||||
return this->String_ <= other;
|
||||
case CompOperator::GREATER:
|
||||
return this->String_ > other;
|
||||
case CompOperator::GREATER_EQUAL:
|
||||
return this->String_ >= other;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CMakeString& CMakeString::Replace(std::string const& matchExpression,
|
||||
std::string const& replaceExpression,
|
||||
Regex regex, cmMakefile* makefile)
|
||||
{
|
||||
if (regex == Regex::Yes) {
|
||||
if (makefile) {
|
||||
makefile->ClearMatches();
|
||||
}
|
||||
|
||||
cmStringReplaceHelper replaceHelper(matchExpression, replaceExpression,
|
||||
makefile);
|
||||
if (!replaceHelper.IsReplaceExpressionValid()) {
|
||||
throw std::invalid_argument(replaceHelper.GetError());
|
||||
}
|
||||
if (!replaceHelper.IsRegularExpressionValid()) {
|
||||
throw std::invalid_argument(
|
||||
cmStrCat("Failed to compile regex \"", matchExpression, '"'));
|
||||
}
|
||||
|
||||
std ::string output;
|
||||
if (!replaceHelper.Replace(this->String_, output)) {
|
||||
throw std::runtime_error(replaceHelper.GetError());
|
||||
}
|
||||
this->String_ = std::move(output);
|
||||
} else {
|
||||
std::string output = this->String_.str();
|
||||
cmsys::SystemTools::ReplaceString(output, matchExpression,
|
||||
replaceExpression);
|
||||
this->String_ = std::move(output);
|
||||
}
|
||||
|
||||
return *this;
|
||||
};
|
||||
|
||||
cmList CMakeString::Match(std::string const& matchExpression,
|
||||
MatchItems matchItems, cmMakefile* makefile) const
|
||||
{
|
||||
if (makefile) {
|
||||
makefile->ClearMatches();
|
||||
}
|
||||
|
||||
// Compile the regular expression.
|
||||
cmsys::RegularExpression re;
|
||||
if (!re.compile(matchExpression)) {
|
||||
throw std::invalid_argument(
|
||||
cmStrCat("Failed to compile regex \"", matchExpression, '"'));
|
||||
}
|
||||
|
||||
cmList output;
|
||||
if (matchItems == MatchItems::Once) {
|
||||
if (re.find(this->String_.data())) {
|
||||
if (makefile) {
|
||||
makefile->StoreMatches(re);
|
||||
}
|
||||
output = re.match();
|
||||
}
|
||||
} else {
|
||||
unsigned optAnchor = 0;
|
||||
if (makefile &&
|
||||
makefile->GetPolicyStatus(cmPolicies::CMP0186) != cmPolicies::NEW) {
|
||||
optAnchor = cmsys::RegularExpression::BOL_AT_OFFSET;
|
||||
}
|
||||
|
||||
// Scan through the input for all matches.
|
||||
std::string::size_type base = 0;
|
||||
unsigned optNonEmpty = 0;
|
||||
while (re.find(this->String_.data(), base, optAnchor | optNonEmpty)) {
|
||||
if (makefile) {
|
||||
makefile->ClearMatches();
|
||||
makefile->StoreMatches(re);
|
||||
}
|
||||
|
||||
output.push_back(re.match());
|
||||
base = re.end();
|
||||
|
||||
if (re.start() == this->String_.length()) {
|
||||
break;
|
||||
}
|
||||
if (re.start() == re.end()) {
|
||||
optNonEmpty = cmsys::RegularExpression::NONEMPTY_AT_OFFSET;
|
||||
} else {
|
||||
optNonEmpty = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
CMakeString CMakeString::Substring(long begin, long count) const
|
||||
{
|
||||
if (begin < 0 || static_cast<size_type>(begin) > this->String_.size()) {
|
||||
throw std::out_of_range(cmStrCat(
|
||||
"begin index: ", begin, " is out of range 0 - ", this->String_.size()));
|
||||
}
|
||||
if (count < -1) {
|
||||
throw std::out_of_range(
|
||||
cmStrCat("end index: ", count, " should be -1 or greater"));
|
||||
}
|
||||
|
||||
return this->String_.substr(static_cast<size_type>(begin),
|
||||
count == -1 ? npos
|
||||
: static_cast<size_type>(count));
|
||||
}
|
||||
|
||||
CMakeString& CMakeString::Strip(StripItems stripItems)
|
||||
{
|
||||
if (stripItems == StripItems::Space) {
|
||||
this->String_ = cmTrimWhitespace(this->String_);
|
||||
} else {
|
||||
this->String_ = cmGeneratorExpression::Preprocess(
|
||||
this->String_, cmGeneratorExpression::StripAllGeneratorExpressions);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CMakeString& CMakeString::Repeat(size_type count)
|
||||
{
|
||||
switch (this->Size()) {
|
||||
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.
|
||||
this->String_ = std::string(count, this->String_[0]);
|
||||
break;
|
||||
default:
|
||||
std::string result;
|
||||
auto size = this->Size();
|
||||
|
||||
result.reserve(size * count);
|
||||
for (auto i = 0u; i < count; ++i) {
|
||||
result.insert(i * size, this->String_.data(), size);
|
||||
}
|
||||
this->String_ = std::move(result);
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
CMakeString& CMakeString::Quote(QuoteItems)
|
||||
{
|
||||
std ::string output;
|
||||
// Escape all regex special characters
|
||||
cmStringReplaceHelper replaceHelper("([][()+*^.$?|\\\\])", R"(\\\1)");
|
||||
if (!replaceHelper.Replace(this->String_, output)) {
|
||||
throw std::runtime_error(replaceHelper.GetError());
|
||||
}
|
||||
|
||||
this->String_ = std::move(output);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CMakeString& CMakeString::Hash(cm::string_view hashAlgorithm)
|
||||
{
|
||||
std::unique_ptr<cmCryptoHash> hash(cmCryptoHash::New(hashAlgorithm));
|
||||
if (hash) {
|
||||
this->String_ = hash->HashString(this->String_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
throw std::invalid_argument(
|
||||
cmStrCat(hashAlgorithm, ": invalid hash algorithm."));
|
||||
}
|
||||
|
||||
CMakeString& CMakeString::FromASCII(string_range codes)
|
||||
{
|
||||
std::string output;
|
||||
output.reserve(codes.size());
|
||||
|
||||
for (auto const& code : codes) {
|
||||
try {
|
||||
auto ch = std::stoi(code);
|
||||
if (ch > 0 && ch < 256) {
|
||||
output += static_cast<char>(ch);
|
||||
} else {
|
||||
throw std::invalid_argument(
|
||||
cmStrCat("Character with code ", code, " does not exist."));
|
||||
}
|
||||
} catch (...) {
|
||||
throw std::invalid_argument(
|
||||
cmStrCat("Character with code ", code, " does not exist."));
|
||||
}
|
||||
}
|
||||
this->String_ = std::move(output);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CMakeString& CMakeString::ToHexadecimal(cm::string_view str)
|
||||
{
|
||||
std::string output(str.size() * 2, ' ');
|
||||
std::string::size_type hexIndex = 0;
|
||||
|
||||
for (auto const& c : str) {
|
||||
std::snprintf(&output[hexIndex], 3, "%.2x", c & 0xFFu);
|
||||
hexIndex += 2;
|
||||
}
|
||||
this->String_ = output;
|
||||
return *this;
|
||||
}
|
||||
|
||||
cm::string_view const CMakeString::RandomDefaultAlphabet{
|
||||
"qwertyuiopasdfghjklzxcvbnm"
|
||||
"QWERTYUIOPASDFGHJKLZXCVBNM"
|
||||
"0123456789"
|
||||
};
|
||||
bool CMakeString::Seeded = false;
|
||||
|
||||
CMakeString& CMakeString::Random(unsigned int seed, std::size_t length,
|
||||
cm::string_view alphabet)
|
||||
{
|
||||
if (alphabet.empty()) {
|
||||
alphabet = RandomDefaultAlphabet;
|
||||
}
|
||||
|
||||
if (length < 1) {
|
||||
throw std::out_of_range("Invoked with bad length.");
|
||||
}
|
||||
|
||||
if (!this->Seeded) {
|
||||
this->Seeded = true;
|
||||
std::srand(seed);
|
||||
}
|
||||
|
||||
double alphabetSize = static_cast<double>(alphabet.size());
|
||||
std::vector<char> result;
|
||||
result.reserve(length + 1);
|
||||
|
||||
for (std::size_t i = 0; i < length; i++) {
|
||||
auto index = static_cast<std::string::size_type>(
|
||||
alphabetSize * std::rand() / (RAND_MAX + 1.0));
|
||||
result.push_back(alphabet[index]);
|
||||
}
|
||||
result.push_back(0);
|
||||
|
||||
this->String_ = result.data();
|
||||
return *this;
|
||||
}
|
||||
|
||||
CMakeString& CMakeString::Timestamp(cm::string_view format, UTC utc)
|
||||
{
|
||||
cmTimestamp timestamp;
|
||||
this->String_ = timestamp.CurrentTime(format, utc == UTC::Yes);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CMakeString& CMakeString::UUID(cm::string_view nameSpace, cm::string_view name,
|
||||
UUIDType type, Case uuidCase)
|
||||
{
|
||||
#if !defined(CMAKE_BOOTSTRAP)
|
||||
cmUuid uuidGenerator;
|
||||
std::vector<unsigned char> uuidNamespace;
|
||||
std::string uuid;
|
||||
|
||||
if (!uuidGenerator.StringToBinary(nameSpace, uuidNamespace)) {
|
||||
throw std::invalid_argument("malformed NAMESPACE UUID");
|
||||
}
|
||||
|
||||
if (type == UUIDType::MD5) {
|
||||
uuid = uuidGenerator.FromMd5(uuidNamespace, name);
|
||||
} else if (type == UUIDType::SHA1) {
|
||||
uuid = uuidGenerator.FromSha1(uuidNamespace, name);
|
||||
}
|
||||
|
||||
if (uuid.empty()) {
|
||||
throw std::runtime_error("generation failed");
|
||||
}
|
||||
|
||||
if (uuidCase == Case::Upper) {
|
||||
uuid = cmSystemTools::UpperCase(uuid);
|
||||
}
|
||||
|
||||
this->String_ = std::move(uuid);
|
||||
return *this;
|
||||
#else
|
||||
throw std::runtime_error("not available during bootstrap");
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <cm/string_view>
|
||||
|
||||
#include "cmList.h"
|
||||
#include "cmRange.h"
|
||||
#include "cmString.hxx"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmValue.h"
|
||||
|
||||
class cmMakefile;
|
||||
|
||||
//
|
||||
// Class offering various string operations which is used by
|
||||
// * CMake string() command
|
||||
// * $<STRING> generator expression
|
||||
//
|
||||
|
||||
namespace cm {
|
||||
|
||||
class CMakeString
|
||||
{
|
||||
public:
|
||||
using size_type = cm::String::size_type;
|
||||
static auto const npos = cm::String::npos;
|
||||
|
||||
using string_range = cmRange<std::vector<std::string>::const_iterator>;
|
||||
|
||||
CMakeString(std::string const& str)
|
||||
: String_(cm::String::borrow(str))
|
||||
{
|
||||
}
|
||||
CMakeString(cm::string_view str)
|
||||
: String_(cm::String::borrow(str))
|
||||
{
|
||||
}
|
||||
CMakeString(cm::String const& str)
|
||||
: String_(str)
|
||||
{
|
||||
}
|
||||
CMakeString(cm::String&& str)
|
||||
: String_(std::move(str))
|
||||
{
|
||||
}
|
||||
CMakeString(cmValue value)
|
||||
: String_(cm::String::borrow(*value))
|
||||
{
|
||||
}
|
||||
CMakeString(string_range range,
|
||||
cm::string_view separator = cm::string_view{})
|
||||
: String_(cmJoin(range, separator))
|
||||
{
|
||||
}
|
||||
|
||||
CMakeString() = default;
|
||||
CMakeString(CMakeString const&) = default;
|
||||
CMakeString(CMakeString&&) = default;
|
||||
|
||||
CMakeString& operator=(CMakeString const& string)
|
||||
{
|
||||
if (this != &string) {
|
||||
this->String_ = string.String_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
CMakeString& operator=(CMakeString&& string) noexcept
|
||||
{
|
||||
if (this != &string) {
|
||||
this->String_ = std::move(string.String_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
CMakeString& operator=(cm::string_view string)
|
||||
{
|
||||
this->String_ = string;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// conversions
|
||||
string_view view() const noexcept { return this->String_.view(); }
|
||||
operator cm::string_view() noexcept { return this->String_.view(); }
|
||||
operator std::string const&() { return this->String_.str(); }
|
||||
|
||||
size_type Size() const { return this->String_.size(); }
|
||||
size_type Length() const { return this->String_.size(); }
|
||||
|
||||
enum class CompOperator
|
||||
{
|
||||
EQUAL,
|
||||
LESS,
|
||||
LESS_EQUAL,
|
||||
GREATER,
|
||||
GREATER_EQUAL
|
||||
};
|
||||
bool Compare(CompOperator op, cm::string_view other);
|
||||
|
||||
enum class FindFrom
|
||||
{
|
||||
Begin,
|
||||
End
|
||||
};
|
||||
size_type Find(cm::string_view substring,
|
||||
FindFrom from = FindFrom::Begin) const
|
||||
{
|
||||
return from == FindFrom::Begin ? this->String_.find(substring)
|
||||
: this->String_.rfind(substring);
|
||||
}
|
||||
|
||||
enum class Regex
|
||||
{
|
||||
No,
|
||||
Yes
|
||||
};
|
||||
// Throw std::invalid_argument if regular expression is invalid
|
||||
// std::runtime_error if replacement failed
|
||||
CMakeString& Replace(std::string const& matchExpression,
|
||||
std::string const& replaceExpression,
|
||||
Regex regex = Regex::No,
|
||||
cmMakefile* makefile = nullptr);
|
||||
|
||||
enum class MatchItems
|
||||
{
|
||||
Once,
|
||||
All
|
||||
};
|
||||
// Throw std::invalid_argument if regular expression is invalid
|
||||
cmList Match(std::string const& matchExpression,
|
||||
MatchItems matchItems = MatchItems::Once,
|
||||
cmMakefile* makefile = nullptr) const;
|
||||
|
||||
CMakeString& Append(cm::string_view str)
|
||||
{
|
||||
this->String_.append(str);
|
||||
return *this;
|
||||
}
|
||||
CMakeString& Append(string_range range)
|
||||
{
|
||||
this->Append(cmJoin(range, {}));
|
||||
return *this;
|
||||
}
|
||||
CMakeString& Prepend(cm::string_view str)
|
||||
{
|
||||
this->String_.insert(0, str);
|
||||
return *this;
|
||||
}
|
||||
CMakeString& Prepend(string_range range)
|
||||
{
|
||||
this->Prepend(cmJoin(range, {}));
|
||||
return *this;
|
||||
}
|
||||
|
||||
CMakeString& ToLower()
|
||||
{
|
||||
this->String_ = cmSystemTools::LowerCase(this->String_);
|
||||
return *this;
|
||||
}
|
||||
CMakeString& ToLower(cm::string_view str)
|
||||
{
|
||||
this->String_ = cmSystemTools::LowerCase(str);
|
||||
return *this;
|
||||
}
|
||||
CMakeString& ToUpper()
|
||||
{
|
||||
this->String_ = cmSystemTools::UpperCase(this->String_);
|
||||
return *this;
|
||||
}
|
||||
CMakeString& ToUpper(cm::string_view str)
|
||||
{
|
||||
this->String_ = cmSystemTools::UpperCase(str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Throw std::out_of_range if pos or count are outside of the expected range
|
||||
CMakeString Substring(long pos = 0, long count = -1) const;
|
||||
|
||||
enum class StripItems
|
||||
{
|
||||
Space,
|
||||
Genex
|
||||
};
|
||||
CMakeString& Strip(StripItems stripItems = StripItems::Space);
|
||||
|
||||
// Throw std::runtime_error if quoting string failed
|
||||
enum class QuoteItems
|
||||
{
|
||||
Regex
|
||||
};
|
||||
CMakeString& Quote(QuoteItems quoteItems = QuoteItems::Regex);
|
||||
|
||||
CMakeString& Repeat(size_type count);
|
||||
|
||||
// Throw std::invalid_argument if the hash algorithm is invalid
|
||||
CMakeString& Hash(cm::string_view hashAlgorithm);
|
||||
|
||||
// Throw std::invalid_argument if one of the codes is invalid
|
||||
CMakeString& FromASCII(string_range codes);
|
||||
CMakeString& ToHexadecimal() { return this->ToHexadecimal(this->String_); }
|
||||
CMakeString& ToHexadecimal(cm::string_view str);
|
||||
|
||||
CMakeString& MakeCIdentifier()
|
||||
{
|
||||
this->String_ = cmSystemTools::MakeCidentifier(this->String_.str());
|
||||
return *this;
|
||||
}
|
||||
CMakeString& MakeCIdentifier(std::string const& str)
|
||||
{
|
||||
this->String_ = cmSystemTools::MakeCidentifier(str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
static cm::string_view const RandomDefaultAlphabet;
|
||||
// Throw std::invalid_argument if the alphabet is invalid
|
||||
// std::out_of_range if length is outside valid range
|
||||
CMakeString& Random(std::size_t length = 5,
|
||||
cm::string_view alphabet = RandomDefaultAlphabet)
|
||||
{
|
||||
return this->Random(cmSystemTools::RandomSeed(), length, alphabet);
|
||||
}
|
||||
CMakeString& Random(unsigned int seed, std::size_t length = 5,
|
||||
cm::string_view alphabet = RandomDefaultAlphabet);
|
||||
|
||||
enum class UTC
|
||||
{
|
||||
No,
|
||||
Yes
|
||||
};
|
||||
CMakeString& Timestamp(cm::string_view format, UTC utc = UTC::No);
|
||||
|
||||
enum class UUIDType
|
||||
{
|
||||
MD5,
|
||||
SHA1
|
||||
};
|
||||
enum class Case
|
||||
{
|
||||
Lower,
|
||||
Upper
|
||||
};
|
||||
// Throw std::invalid_argument if namespace or the type are invalid
|
||||
// std::runtime_error if the UUID cannot be generated
|
||||
CMakeString& UUID(cm::string_view nameSpace, cm::string_view name,
|
||||
UUIDType type, Case uuidCase = Case::Lower);
|
||||
|
||||
private:
|
||||
static bool Seeded;
|
||||
cm::String String_;
|
||||
};
|
||||
}
|
||||
+181
-357
@@ -5,9 +5,9 @@
|
||||
|
||||
#include "cmStringCommand.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
@@ -22,22 +22,14 @@
|
||||
#include <cm3p/json/value.h>
|
||||
#include <cm3p/json/writer.h>
|
||||
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
|
||||
#include "cmCryptoHash.h"
|
||||
#include "cmCMakeString.hxx"
|
||||
#include "cmExecutionStatus.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmList.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmPolicies.h"
|
||||
#include "cmRange.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmStringReplaceHelper.h"
|
||||
#include "cmSubcommandTable.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTimestamp.h"
|
||||
#include "cmUuid.h"
|
||||
#include "cmValue.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -62,13 +54,16 @@ bool HandleHashCommand(std::vector<std::string> const& args,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<cmCryptoHash> hash(cmCryptoHash::New(args[0]));
|
||||
if (hash) {
|
||||
std::string out = hash->HashString(args[2]);
|
||||
status.GetMakefile().AddDefinition(args[1], out);
|
||||
cm::CMakeString data{ args[2] };
|
||||
|
||||
try {
|
||||
data.Hash(args[0]);
|
||||
status.GetMakefile().AddDefinition(args[1], data);
|
||||
return true;
|
||||
} catch (std::exception const& e) {
|
||||
status.SetError(e.what());
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HandleToUpperLowerCommand(std::vector<std::string> const& args,
|
||||
@@ -80,16 +75,16 @@ bool HandleToUpperLowerCommand(std::vector<std::string> const& args,
|
||||
}
|
||||
|
||||
std::string const& outvar = args[2];
|
||||
std::string output;
|
||||
cm::CMakeString data{ args[1] };
|
||||
|
||||
if (toUpper) {
|
||||
output = cmSystemTools::UpperCase(args[1]);
|
||||
data.ToUpper();
|
||||
} else {
|
||||
output = cmSystemTools::LowerCase(args[1]);
|
||||
data.ToLower();
|
||||
}
|
||||
|
||||
// Store the output in the provided variable.
|
||||
status.GetMakefile().AddDefinition(outvar, output);
|
||||
status.GetMakefile().AddDefinition(outvar, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -112,23 +107,17 @@ bool HandleAsciiCommand(std::vector<std::string> const& args,
|
||||
status.SetError("No output variable specified");
|
||||
return false;
|
||||
}
|
||||
std::string::size_type cc;
|
||||
std::string const& outvar = args.back();
|
||||
std::string output;
|
||||
for (cc = 1; cc < args.size() - 1; cc++) {
|
||||
int ch = atoi(args[cc].c_str());
|
||||
if (ch > 0 && ch < 256) {
|
||||
output += static_cast<char>(ch);
|
||||
} else {
|
||||
std::string error =
|
||||
cmStrCat("Character with code ", args[cc], " does not exist.");
|
||||
status.SetError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
std::string const& outvar = args.back();
|
||||
cm::CMakeString data;
|
||||
data.FromASCII(cmMakeRange(args).advance(1).retreat(1));
|
||||
status.GetMakefile().AddDefinition(outvar, data);
|
||||
return true;
|
||||
} catch (std::exception const& e) {
|
||||
status.SetError(e.what());
|
||||
return false;
|
||||
}
|
||||
// Store the output in the provided variable.
|
||||
status.GetMakefile().AddDefinition(outvar, output);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HandleHexCommand(std::vector<std::string> const& args,
|
||||
@@ -138,17 +127,13 @@ bool HandleHexCommand(std::vector<std::string> const& args,
|
||||
status.SetError("Incorrect number of arguments");
|
||||
return false;
|
||||
}
|
||||
auto const& instr = args[1];
|
||||
|
||||
auto const& outvar = args[2];
|
||||
std::string output(instr.size() * 2, ' ');
|
||||
cm::CMakeString data{ args[1] };
|
||||
|
||||
std::string::size_type hexIndex = 0;
|
||||
for (auto const& c : instr) {
|
||||
snprintf(&output[hexIndex], 3, "%.2x", c & 0xFFu);
|
||||
hexIndex += 2;
|
||||
}
|
||||
data.ToHexadecimal();
|
||||
|
||||
status.GetMakefile().AddDefinition(outvar, output);
|
||||
status.GetMakefile().AddDefinition(outvar, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -239,33 +224,21 @@ bool RegexMatch(std::vector<std::string> const& args,
|
||||
{
|
||||
//"STRING(REGEX MATCH <regular_expression> <output variable>
|
||||
// <input> [<input>...])\n";
|
||||
std::string const& regex = args[2];
|
||||
std::string const& outvar = args[3];
|
||||
try {
|
||||
std::string const& regex = args[2];
|
||||
std::string const& outvar = args[3];
|
||||
cm::CMakeString data{ cmMakeRange(args).advance(4) };
|
||||
|
||||
status.GetMakefile().ClearMatches();
|
||||
// Compile the regular expression.
|
||||
cmsys::RegularExpression re;
|
||||
if (!re.compile(regex)) {
|
||||
std::string e =
|
||||
"sub-command REGEX, mode MATCH failed to compile regex \"" + regex +
|
||||
"\".";
|
||||
status.SetError(e);
|
||||
auto result = data.Match(regex, cm::CMakeString::MatchItems::Once,
|
||||
&status.GetMakefile());
|
||||
// Store the result in the provided variable.
|
||||
status.GetMakefile().AddDefinition(outvar, result.to_string());
|
||||
return true;
|
||||
} catch (std::exception const& e) {
|
||||
status.SetError(
|
||||
cmStrCat("sub-command REGEX, mode MATCH: ", e.what(), '.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Concatenate all the last arguments together.
|
||||
std::string input = cmJoin(cmMakeRange(args).advance(4), std::string());
|
||||
|
||||
// Scan through the input for all matches.
|
||||
std::string output;
|
||||
if (re.find(input)) {
|
||||
status.GetMakefile().StoreMatches(re);
|
||||
output = re.match();
|
||||
}
|
||||
|
||||
// Store the output in the provided variable.
|
||||
status.GetMakefile().AddDefinition(outvar, output);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegexMatchAll(std::vector<std::string> const& args,
|
||||
@@ -273,55 +246,21 @@ bool RegexMatchAll(std::vector<std::string> const& args,
|
||||
{
|
||||
//"STRING(REGEX MATCHALL <regular_expression> <output variable> <input>
|
||||
// [<input>...])\n";
|
||||
std::string const& regex = args[2];
|
||||
std::string const& outvar = args[3];
|
||||
try {
|
||||
std::string const& regex = args[2];
|
||||
std::string const& outvar = args[3];
|
||||
cm::CMakeString data{ cmMakeRange(args).advance(4) };
|
||||
|
||||
status.GetMakefile().ClearMatches();
|
||||
// Compile the regular expression.
|
||||
cmsys::RegularExpression re;
|
||||
if (!re.compile(regex)) {
|
||||
std::string e =
|
||||
"sub-command REGEX, mode MATCHALL failed to compile regex \"" + regex +
|
||||
"\".";
|
||||
status.SetError(e);
|
||||
auto result = data.Match(regex, cm::CMakeString::MatchItems::All,
|
||||
&status.GetMakefile());
|
||||
// Store the result in the provided variable.
|
||||
status.GetMakefile().AddDefinition(outvar, result.to_string());
|
||||
return true;
|
||||
} catch (std::exception const& e) {
|
||||
status.SetError(
|
||||
cmStrCat("sub-command REGEX, mode MATCHALL: ", e.what(), '.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Concatenate all the last arguments together.
|
||||
std::string input = cmJoin(cmMakeRange(args).advance(4), std::string());
|
||||
|
||||
unsigned optAnchor = 0;
|
||||
if (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0186) !=
|
||||
cmPolicies::NEW) {
|
||||
optAnchor = cmsys::RegularExpression::BOL_AT_OFFSET;
|
||||
}
|
||||
|
||||
// Scan through the input for all matches.
|
||||
std::string output;
|
||||
std::string::size_type base = 0;
|
||||
unsigned optNonEmpty = 0;
|
||||
while (re.find(input, base, optAnchor | optNonEmpty)) {
|
||||
status.GetMakefile().ClearMatches();
|
||||
status.GetMakefile().StoreMatches(re);
|
||||
if (!output.empty() || optNonEmpty) {
|
||||
output += ";";
|
||||
}
|
||||
output += re.match();
|
||||
base = re.end();
|
||||
|
||||
if (re.start() == input.length()) {
|
||||
break;
|
||||
}
|
||||
if (re.start() == re.end()) {
|
||||
optNonEmpty = cmsys::RegularExpression::NONEMPTY_AT_OFFSET;
|
||||
} else {
|
||||
optNonEmpty = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Store the output in the provided variable.
|
||||
status.GetMakefile().AddDefinition(outvar, output);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegexReplace(std::vector<std::string> const& args,
|
||||
@@ -332,38 +271,20 @@ bool RegexReplace(std::vector<std::string> const& args,
|
||||
std::string const& regex = args[2];
|
||||
std::string const& replace = args[3];
|
||||
std::string const& outvar = args[4];
|
||||
cmStringReplaceHelper replaceHelper(regex, replace, &status.GetMakefile());
|
||||
|
||||
if (!replaceHelper.IsReplaceExpressionValid()) {
|
||||
try {
|
||||
cm::CMakeString data{ cmMakeRange(args).advance(5) };
|
||||
|
||||
data.Replace(regex, replace, cm::CMakeString::Regex::Yes,
|
||||
&status.GetMakefile());
|
||||
// Store the result in the provided variable.
|
||||
status.GetMakefile().AddDefinition(outvar, data);
|
||||
return true;
|
||||
} catch (std::exception const& e) {
|
||||
status.SetError(
|
||||
"sub-command REGEX, mode REPLACE: " + replaceHelper.GetError() + ".");
|
||||
cmStrCat("sub-command REGEX, mode REPLACE: ", e.what(), '.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
status.GetMakefile().ClearMatches();
|
||||
|
||||
if (!replaceHelper.IsRegularExpressionValid()) {
|
||||
std::string e =
|
||||
"sub-command REGEX, mode REPLACE failed to compile regex \"" + regex +
|
||||
"\".";
|
||||
status.SetError(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Concatenate all the last arguments together.
|
||||
std::string const input =
|
||||
cmJoin(cmMakeRange(args).advance(5), std::string());
|
||||
std::string output;
|
||||
|
||||
if (!replaceHelper.Replace(input, output)) {
|
||||
status.SetError(
|
||||
"sub-command REGEX, mode REPLACE: " + replaceHelper.GetError() + ".");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store the output in the provided variable.
|
||||
status.GetMakefile().AddDefinition(outvar, output);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegexQuote(std::vector<std::string> const& args,
|
||||
@@ -371,21 +292,19 @@ bool RegexQuote(std::vector<std::string> const& args,
|
||||
{
|
||||
//"STRING(REGEX QUOTE <output variable> <input> [<input>...]\n"
|
||||
std::string const& outvar = args[2];
|
||||
std::string const input =
|
||||
cmJoin(cmMakeRange(args).advance(3), std::string());
|
||||
std::string output;
|
||||
cm::CMakeString data{ cmMakeRange(args).advance(3) };
|
||||
|
||||
// Escape all regex special characters
|
||||
cmStringReplaceHelper replaceHelper("([][()+*^.$?|\\\\])", R"(\\\1)");
|
||||
if (!replaceHelper.Replace(input, output)) {
|
||||
try {
|
||||
// Escape all regex special characters
|
||||
data.Quote();
|
||||
// Store the output in the provided variable.
|
||||
status.GetMakefile().AddDefinition(outvar, data);
|
||||
return true;
|
||||
} catch (std::exception const& e) {
|
||||
status.SetError(
|
||||
"sub-command REGEX, mode QUOTE: " + replaceHelper.GetError() + ".");
|
||||
cmStrCat("sub-command REGEX, mode QUOTE: ", e.what(), '.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store the output in the provided variable.
|
||||
status.GetMakefile().AddDefinition(outvar, output);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HandleFindCommand(std::vector<std::string> const& args,
|
||||
@@ -423,19 +342,14 @@ bool HandleFindCommand(std::vector<std::string> const& args,
|
||||
}
|
||||
|
||||
// try to find the character and return its position
|
||||
size_t pos;
|
||||
if (!reverseMode) {
|
||||
pos = sstring.find(schar);
|
||||
} else {
|
||||
pos = sstring.rfind(schar);
|
||||
}
|
||||
if (std::string::npos != pos) {
|
||||
status.GetMakefile().AddDefinition(outvar, std::to_string(pos));
|
||||
return true;
|
||||
}
|
||||
auto pos = cm::CMakeString{ sstring }.Find(
|
||||
schar,
|
||||
reverseMode ? cm::CMakeString::FindFrom::End
|
||||
: cm::CMakeString::FindFrom::Begin);
|
||||
|
||||
status.GetMakefile().AddDefinition(
|
||||
outvar, pos != cm::CMakeString::npos ? std::to_string(pos) : "-1");
|
||||
|
||||
// the character was not found, but this is not really an error
|
||||
status.GetMakefile().AddDefinition(outvar, "-1");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -462,25 +376,22 @@ bool HandleCompareCommand(std::vector<std::string> const& args,
|
||||
std::string const& right = args[3];
|
||||
std::string const& outvar = args[4];
|
||||
bool result;
|
||||
cm::CMakeString::CompOperator op = cm::CMakeString::CompOperator::EQUAL;
|
||||
if (mode == "LESS") {
|
||||
result = (left < right);
|
||||
op = cm::CMakeString::CompOperator::LESS;
|
||||
} else if (mode == "LESS_EQUAL") {
|
||||
result = (left <= right);
|
||||
op = cm::CMakeString::CompOperator::LESS_EQUAL;
|
||||
} else if (mode == "GREATER") {
|
||||
result = (left > right);
|
||||
op = cm::CMakeString::CompOperator::GREATER;
|
||||
} else if (mode == "GREATER_EQUAL") {
|
||||
result = (left >= right);
|
||||
} else if (mode == "EQUAL") {
|
||||
result = (left == right);
|
||||
} else // if(mode == "NOTEQUAL")
|
||||
{
|
||||
result = !(left == right);
|
||||
op = cm::CMakeString::CompOperator::GREATER_EQUAL;
|
||||
}
|
||||
if (result) {
|
||||
status.GetMakefile().AddDefinition(outvar, "1");
|
||||
} else {
|
||||
status.GetMakefile().AddDefinition(outvar, "0");
|
||||
result = cm::CMakeString{ left }.Compare(op, right);
|
||||
if (mode == "NOTEQUAL") {
|
||||
result = !result;
|
||||
}
|
||||
|
||||
status.GetMakefile().AddDefinition(outvar, result ? "1" : "0");
|
||||
return true;
|
||||
}
|
||||
std::string e = "sub-command COMPARE does not recognize mode " + mode;
|
||||
@@ -496,17 +407,19 @@ bool HandleReplaceCommand(std::vector<std::string> const& args,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string const& matchExpression = args[1];
|
||||
std::string const& replaceExpression = args[2];
|
||||
std::string const& variableName = args[3];
|
||||
try {
|
||||
std::string const& matchExpression = args[1];
|
||||
std::string const& replaceExpression = args[2];
|
||||
std::string const& variableName = args[3];
|
||||
cm::CMakeString data{ cmMakeRange(args).advance(4) };
|
||||
|
||||
std::string input = cmJoin(cmMakeRange(args).advance(4), std::string());
|
||||
|
||||
cmsys::SystemTools::ReplaceString(input, matchExpression.c_str(),
|
||||
replaceExpression.c_str());
|
||||
|
||||
status.GetMakefile().AddDefinition(variableName, input);
|
||||
return true;
|
||||
data.Replace(matchExpression, replaceExpression);
|
||||
status.GetMakefile().AddDefinition(variableName, data);
|
||||
return true;
|
||||
} catch (std::exception const& e) {
|
||||
status.SetError(cmStrCat("sub-command REPLACE: ", e.what(), '.'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool HandleSubstringCommand(std::vector<std::string> const& args,
|
||||
@@ -517,25 +430,19 @@ bool HandleSubstringCommand(std::vector<std::string> const& args,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string const& stringValue = args[1];
|
||||
int begin = atoi(args[2].c_str());
|
||||
int end = atoi(args[3].c_str());
|
||||
std::string const& variableName = args[4];
|
||||
try {
|
||||
std::string const& stringValue = args[1];
|
||||
int begin = atoi(args[2].c_str());
|
||||
int end = atoi(args[3].c_str());
|
||||
std::string const& variableName = args[4];
|
||||
|
||||
size_t stringLength = stringValue.size();
|
||||
int intStringLength = static_cast<int>(stringLength);
|
||||
if (begin < 0 || begin > intStringLength) {
|
||||
status.SetError(
|
||||
cmStrCat("begin index: ", begin, " is out of range 0 - ", stringLength));
|
||||
cm::CMakeString data{ stringValue };
|
||||
status.GetMakefile().AddDefinition(variableName,
|
||||
data.Substring(begin, end));
|
||||
} catch (std::exception const& e) {
|
||||
status.SetError(e.what());
|
||||
return false;
|
||||
}
|
||||
if (end < -1) {
|
||||
status.SetError(cmStrCat("end index: ", end, " should be -1 or greater"));
|
||||
return false;
|
||||
}
|
||||
|
||||
status.GetMakefile().AddDefinition(variableName,
|
||||
stringValue.substr(begin, end));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -550,11 +457,8 @@ bool HandleLengthCommand(std::vector<std::string> const& args,
|
||||
std::string const& stringValue = args[1];
|
||||
std::string const& variableName = args[2];
|
||||
|
||||
size_t length = stringValue.size();
|
||||
char buffer[1024];
|
||||
snprintf(buffer, sizeof(buffer), "%d", static_cast<int>(length));
|
||||
|
||||
status.GetMakefile().AddDefinition(variableName, buffer);
|
||||
status.GetMakefile().AddDefinition(
|
||||
variableName, std::to_string(cm::CMakeString{ stringValue }.Length()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -572,12 +476,10 @@ bool HandleAppendCommand(std::vector<std::string> const& args,
|
||||
}
|
||||
|
||||
auto const& variableName = args[1];
|
||||
cm::CMakeString data{ status.GetMakefile().GetDefinition(variableName) };
|
||||
|
||||
cm::string_view oldView{ status.GetMakefile().GetSafeDefinition(
|
||||
variableName) };
|
||||
|
||||
auto const newValue = cmJoin(cmMakeRange(args).advance(2), {}, oldView);
|
||||
status.GetMakefile().AddDefinition(variableName, newValue);
|
||||
data.Append(cmMakeRange(args).advance(2));
|
||||
status.GetMakefile().AddDefinition(variableName, data);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -596,13 +498,10 @@ bool HandlePrependCommand(std::vector<std::string> const& args,
|
||||
}
|
||||
|
||||
std::string const& variable = args[1];
|
||||
cm::CMakeString data{ status.GetMakefile().GetDefinition(variable) };
|
||||
|
||||
std::string value = cmJoin(cmMakeRange(args).advance(2), std::string());
|
||||
cmValue oldValue = status.GetMakefile().GetDefinition(variable);
|
||||
if (oldValue) {
|
||||
value += *oldValue;
|
||||
}
|
||||
status.GetMakefile().AddDefinition(variable, value);
|
||||
data.Prepend(cmMakeRange(args).advance(2));
|
||||
status.GetMakefile().AddDefinition(variable, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -634,9 +533,9 @@ bool joinImpl(std::vector<std::string> const& args, std::string const& glue,
|
||||
std::string const& variableName = args[varIdx];
|
||||
// NOTE Items to concat/join placed right after the variable for
|
||||
// both `CONCAT` and `JOIN` sub-commands.
|
||||
std::string value = cmJoin(cmMakeRange(args).advance(varIdx + 1), glue);
|
||||
cm::CMakeString data{ cmMakeRange(args).advance(varIdx + 1), glue };
|
||||
|
||||
makefile.AddDefinition(variableName, value);
|
||||
makefile.AddDefinition(variableName, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -652,7 +551,7 @@ bool HandleMakeCIdentifierCommand(std::vector<std::string> const& args,
|
||||
std::string const& variableName = args[2];
|
||||
|
||||
status.GetMakefile().AddDefinition(variableName,
|
||||
cmSystemTools::MakeCidentifier(input));
|
||||
cm::CMakeString{}.MakeCIdentifier(input));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -664,14 +563,11 @@ bool HandleGenexStripCommand(std::vector<std::string> const& args,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string const& input = args[1];
|
||||
|
||||
std::string result = cmGeneratorExpression::Preprocess(
|
||||
input, cmGeneratorExpression::StripAllGeneratorExpressions);
|
||||
|
||||
cm::CMakeString data{ args[1] };
|
||||
std::string const& variableName = args[2];
|
||||
|
||||
status.GetMakefile().AddDefinition(variableName, result);
|
||||
status.GetMakefile().AddDefinition(
|
||||
variableName, data.Strip(cm::CMakeString::StripItems::Genex));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -683,36 +579,10 @@ bool HandleStripCommand(std::vector<std::string> const& args,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string const& stringValue = args[1];
|
||||
cm::CMakeString data{ args[1] };
|
||||
std::string const& variableName = args[2];
|
||||
size_t inStringLength = stringValue.size();
|
||||
size_t startPos = inStringLength + 1;
|
||||
size_t endPos = 0;
|
||||
char const* ptr = stringValue.c_str();
|
||||
size_t cc;
|
||||
for (cc = 0; cc < inStringLength; ++cc) {
|
||||
if (!cmIsSpace(*ptr)) {
|
||||
if (startPos > inStringLength) {
|
||||
startPos = cc;
|
||||
}
|
||||
endPos = cc;
|
||||
}
|
||||
++ptr;
|
||||
}
|
||||
|
||||
size_t outLength = 0;
|
||||
|
||||
// if the input string didn't contain any non-space characters, return
|
||||
// an empty string
|
||||
if (startPos > inStringLength) {
|
||||
outLength = 0;
|
||||
startPos = 0;
|
||||
} else {
|
||||
outLength = endPos - startPos + 1;
|
||||
}
|
||||
|
||||
status.GetMakefile().AddDefinition(variableName,
|
||||
stringValue.substr(startPos, outLength));
|
||||
status.GetMakefile().AddDefinition(variableName, data.Strip());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -744,30 +614,12 @@ bool HandleRepeatCommand(std::vector<std::string> const& args,
|
||||
return true;
|
||||
}
|
||||
|
||||
auto const& stringValue = args[ArgPos::VALUE];
|
||||
cm::CMakeString data{ args[ArgPos::VALUE] };
|
||||
data.Repeat(times);
|
||||
|
||||
auto const& variableName = args[ArgPos::OUTPUT_VARIABLE];
|
||||
auto const 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;
|
||||
}
|
||||
|
||||
makefile.AddDefinition(variableName, result);
|
||||
makefile.AddDefinition(variableName, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -779,14 +631,10 @@ bool HandleRandomCommand(std::vector<std::string> const& args,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool seeded = false;
|
||||
int length = 5;
|
||||
cm::string_view alphabet;
|
||||
bool force_seed = false;
|
||||
unsigned int seed = 0;
|
||||
int length = 5;
|
||||
char const cmStringCommandDefaultAlphabet[] = "qwertyuiopasdfghjklzxcvbnm"
|
||||
"QWERTYUIOPASDFGHJKLZXCVBNM"
|
||||
"0123456789";
|
||||
std::string alphabet;
|
||||
|
||||
if (args.size() > 3) {
|
||||
size_t i = 1;
|
||||
@@ -806,37 +654,22 @@ bool HandleRandomCommand(std::vector<std::string> const& args,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (alphabet.empty()) {
|
||||
alphabet = cmStringCommandDefaultAlphabet;
|
||||
}
|
||||
|
||||
double sizeofAlphabet = static_cast<double>(alphabet.size());
|
||||
if (sizeofAlphabet < 1) {
|
||||
status.SetError("sub-command RANDOM invoked with bad alphabet.");
|
||||
try {
|
||||
cm::CMakeString data;
|
||||
std::string const& variableName = args.back();
|
||||
|
||||
if (force_seed) {
|
||||
data.Random(seed, length, alphabet);
|
||||
} else {
|
||||
data.Random(length, alphabet);
|
||||
}
|
||||
status.GetMakefile().AddDefinition(variableName, data);
|
||||
return true;
|
||||
} catch (std::exception const& e) {
|
||||
status.SetError(cmStrCat("sub-command RANDOM: ", e.what(), '.'));
|
||||
return false;
|
||||
}
|
||||
if (length < 1) {
|
||||
status.SetError("sub-command RANDOM invoked with bad length.");
|
||||
return false;
|
||||
}
|
||||
std::string const& variableName = args.back();
|
||||
|
||||
std::vector<char> result;
|
||||
|
||||
if (!seeded || force_seed) {
|
||||
seeded = true;
|
||||
srand(force_seed ? seed : cmSystemTools::RandomSeed());
|
||||
}
|
||||
|
||||
char const* alphaPtr = alphabet.c_str();
|
||||
for (int cc = 0; cc < length; cc++) {
|
||||
int idx = static_cast<int>(sizeofAlphabet * rand() / (RAND_MAX + 1.0));
|
||||
result.push_back(*(alphaPtr + idx));
|
||||
}
|
||||
result.push_back(0);
|
||||
|
||||
status.GetMakefile().AddDefinition(variableName, result.data());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HandleTimestampCommand(std::vector<std::string> const& args,
|
||||
@@ -855,26 +688,28 @@ bool HandleTimestampCommand(std::vector<std::string> const& args,
|
||||
|
||||
std::string const& outputVariable = args[argsIndex++];
|
||||
|
||||
std::string formatString;
|
||||
cm::string_view formatString;
|
||||
if (args.size() > argsIndex && args[argsIndex] != "UTC") {
|
||||
formatString = args[argsIndex++];
|
||||
}
|
||||
|
||||
bool utcFlag = false;
|
||||
cm::CMakeString::UTC utcFlag = cm::CMakeString::UTC::No;
|
||||
if (args.size() > argsIndex) {
|
||||
if (args[argsIndex] == "UTC") {
|
||||
utcFlag = true;
|
||||
utcFlag = cm::CMakeString::UTC::Yes;
|
||||
} else {
|
||||
std::string e = " TIMESTAMP sub-command does not recognize option " +
|
||||
args[argsIndex] + ".";
|
||||
std::string e =
|
||||
cmStrCat(" TIMESTAMP sub-command does not recognize option ",
|
||||
args[argsIndex], '.');
|
||||
status.SetError(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
cmTimestamp timestamp;
|
||||
std::string result = timestamp.CurrentTime(formatString, utcFlag);
|
||||
status.GetMakefile().AddDefinition(outputVariable, result);
|
||||
cm::CMakeString data;
|
||||
|
||||
status.GetMakefile().AddDefinition(outputVariable,
|
||||
data.Timestamp(formatString, utcFlag));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -892,10 +727,10 @@ bool HandleUuidCommand(std::vector<std::string> const& args,
|
||||
|
||||
std::string const& outputVariable = args[argsIndex++];
|
||||
|
||||
std::string uuidNamespaceString;
|
||||
std::string uuidName;
|
||||
std::string uuidType;
|
||||
bool uuidUpperCase = false;
|
||||
cm::string_view uuidNamespaceString;
|
||||
cm::string_view uuidName;
|
||||
cm::CMakeString::UUIDType uuidType = cm::CMakeString::UUIDType::MD5;
|
||||
cm::CMakeString::Case uuidCase = cm::CMakeString::Case::Lower;
|
||||
|
||||
while (args.size() > argsIndex) {
|
||||
if (args[argsIndex] == "NAMESPACE") {
|
||||
@@ -918,50 +753,39 @@ bool HandleUuidCommand(std::vector<std::string> const& args,
|
||||
status.SetError("UUID sub-command, TYPE requires a value.");
|
||||
return false;
|
||||
}
|
||||
uuidType = args[argsIndex++];
|
||||
if (args[argsIndex] == "MD5") {
|
||||
uuidType = cm::CMakeString::UUIDType::MD5;
|
||||
} else if (args[argsIndex] == "SHA1") {
|
||||
uuidType = cm::CMakeString::UUIDType::SHA1;
|
||||
} else {
|
||||
status.SetError(
|
||||
cmStrCat("UUID sub-command, unknown TYPE '", args[argsIndex], "'."));
|
||||
return false;
|
||||
}
|
||||
argsIndex++;
|
||||
} else if (args[argsIndex] == "UPPER") {
|
||||
++argsIndex;
|
||||
uuidUpperCase = true;
|
||||
uuidCase = cm::CMakeString::Case::Upper;
|
||||
} else {
|
||||
std::string e =
|
||||
"UUID sub-command does not recognize option " + args[argsIndex] + ".";
|
||||
std::string e = cmStrCat("UUID sub-command does not recognize option ",
|
||||
args[argsIndex], '.');
|
||||
status.SetError(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string uuid;
|
||||
cmUuid uuidGenerator;
|
||||
try {
|
||||
cm::CMakeString data;
|
||||
|
||||
std::vector<unsigned char> uuidNamespace;
|
||||
if (!uuidGenerator.StringToBinary(uuidNamespaceString, uuidNamespace)) {
|
||||
status.SetError("UUID sub-command, malformed NAMESPACE UUID.");
|
||||
data.UUID(uuidNamespaceString, uuidName, uuidType, uuidCase);
|
||||
status.GetMakefile().AddDefinition(outputVariable, data);
|
||||
return true;
|
||||
} catch (std::exception const& e) {
|
||||
status.SetError(cmStrCat("UUID sub-command, ", e.what(), '.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (uuidType == "MD5") {
|
||||
uuid = uuidGenerator.FromMd5(uuidNamespace, uuidName);
|
||||
} else if (uuidType == "SHA1") {
|
||||
uuid = uuidGenerator.FromSha1(uuidNamespace, uuidName);
|
||||
} else {
|
||||
std::string e = "UUID sub-command, unknown TYPE '" + uuidType + "'.";
|
||||
status.SetError(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (uuid.empty()) {
|
||||
status.SetError("UUID sub-command, generation failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (uuidUpperCase) {
|
||||
uuid = cmSystemTools::UpperCase(uuid);
|
||||
}
|
||||
|
||||
status.GetMakefile().AddDefinition(outputVariable, uuid);
|
||||
return true;
|
||||
#else
|
||||
status.SetError(cmStrCat(args[0], " not available during bootstrap"));
|
||||
status.SetError("UUID sub-command not available during bootstrap.");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user