summaryrefslogtreecommitdiffstats
path: root/Source/cmStringAlgorithms.h
blob: 149e0ade6f351fcdd3d99978b8c23f63d2b0c575 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#ifndef cmStringAlgorithms_h
#define cmStringAlgorithms_h

#include "cmConfigure.h" // IWYU pragma: keep

#include "cmRange.h"
#include "cm_string_view.hxx"
#include <algorithm>
#include <iterator>
#include <sstream>
#include <string.h>
#include <string>
#include <utility>
#include <vector>

typedef cmRange<std::vector<std::string>::const_iterator> cmStringRange;

struct cmStrCmp
{
  cmStrCmp(const char* test)
    : m_test(test)
  {
  }
  cmStrCmp(std::string test)
    : m_test(std::move(test))
  {
  }

  bool operator()(const std::string& input) const { return m_test == input; }

  bool operator()(const char* input) const
  {
    return strcmp(input, m_test.c_str()) == 0;
  }

private:
  const std::string m_test;
};

template <typename Range>
std::string cmJoin(Range const& r, const char* delimiter)
{
  if (r.empty()) {
    return std::string();
  }
  std::ostringstream os;
  typedef typename Range::value_type ValueType;
  typedef typename Range::const_iterator InputIt;
  const InputIt first = r.begin();
  InputIt last = r.end();
  --last;
  std::copy(first, last, std::ostream_iterator<ValueType>(os, delimiter));

  os << *last;

  return os.str();
}

template <typename Range>
std::string cmJoin(Range const& r, std::string const& delimiter)
{
  return cmJoin(r, delimiter.c_str());
}

template <typename Range>
std::string cmWrap(std::string const& prefix, Range const& r,
                   std::string const& suffix, std::string const& sep)
{
  if (r.empty()) {
    return std::string();
  }
  return prefix + cmJoin(r, suffix + sep + prefix) + suffix;
}

template <typename Range>
std::string cmWrap(char prefix, Range const& r, char suffix,
                   std::string const& sep)
{
  return cmWrap(std::string(1, prefix), r, std::string(1, suffix), sep);
}

/** Returns true if string @a str starts with the character @a prefix.  **/
inline bool cmHasPrefix(cm::string_view str, char prefix)
{
  return !str.empty() && (str.front() == prefix);
}

/** Returns true if string @a str starts with string @a prefix.  **/
inline bool cmHasPrefix(cm::string_view str, cm::string_view prefix)
{
  return str.compare(0, prefix.size(), prefix) == 0;
}

/** Returns true if string @a str starts with string @a prefix.  **/
template <size_t N>
inline bool cmHasLiteralPrefix(cm::string_view str, const char (&prefix)[N])
{
  return cmHasPrefix(str, cm::string_view(prefix, N - 1));
}

/** Returns true if string @a str ends with the character @a suffix.  **/
inline bool cmHasSuffix(cm::string_view str, char suffix)
{
  return !str.empty() && (str.back() == suffix);
}

/** Returns true if string @a str ends with string @a suffix.  **/
inline bool cmHasSuffix(cm::string_view str, cm::string_view suffix)
{
  return str.size() >= suffix.size() &&
    str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}

/** Returns true if string @a str ends with string @a suffix.  **/
template <size_t N>
inline bool cmHasLiteralSuffix(cm::string_view str, const char (&suffix)[N])
{
  return cmHasSuffix(str, cm::string_view(suffix, N - 1));
}

/** Removes an existing suffix character of from the string @a str.  **/
inline void cmStripSuffixIfExists(std::string& str, char suffix)
{
  if (cmHasSuffix(str, suffix)) {
    str.pop_back();
  }
}

/** Removes an existing suffix string of from the string @a str.  **/
inline void cmStripSuffixIfExists(std::string& str, cm::string_view suffix)
{
  if (cmHasSuffix(str, suffix)) {
    str.resize(str.size() - suffix.size());
  }
}

#endif