cprover
Toggle main menu visibility
Loading...
Searching...
No Matches
string_utils.cpp
Go to the documentation of this file.
1
/*******************************************************************\
2
3
Module:
4
5
Author: Daniel Poetzl
6
7
\*******************************************************************/
8
9
#include "
string_utils.h
"
10
#include "
exception_utils.h
"
11
#include "
invariant.h
"
12
13
#include <algorithm>
14
#include <cctype>
15
#include <iomanip>
16
21
std::string
strip_string
(std::string_view s)
22
{
23
auto
pred=[](
char
c){
return
std::isspace(c); };
24
25
std::string_view::const_iterator left =
26
std::find_if_not(s.begin(), s.end(), pred);
27
if
(left==s.end())
28
return
""
;
29
30
std::size_t i = std::distance(s.begin(), left);
31
32
std::string_view::const_reverse_iterator right =
33
std::find_if_not(s.rbegin(), s.rend(), pred);
34
std::size_t j = std::distance(right, s.rend()) - 1;
35
36
// copy happens here; this could return a view in the future
37
return
std::string{s.substr(i, (j - i + 1))};
38
}
39
40
void
split_string
(
41
std::string_view s,
42
char
delim,
43
std::vector<std::string> &result,
44
bool
strip,
45
bool
remove_empty)
46
{
47
PRECONDITION
(result.empty());
48
// delim can't be a space character if using strip
49
PRECONDITION
(!std::isspace(delim) || !strip);
50
51
if
(s.empty())
52
{
53
if
(!remove_empty)
54
result.push_back(
""
);
55
return
;
56
}
57
58
std::size_t n = s.length();
59
INVARIANT
(n > 0,
"Empty string case should already be handled"
);
60
61
std::size_t start = 0;
62
std::size_t i;
63
64
for
(i=0; i<n; i++)
65
{
66
if
(s[i]==delim)
67
{
68
// result owns std::strings rather than string_views: callers
69
// routinely pass a temporary as `s` (e.g. some_function()
70
// returning std::string), so the input may not outlive the
71
// result.
72
std::string new_s = std::string{s.substr(start, i - start)};
73
74
if
(strip)
75
new_s=
strip_string
(new_s);
76
77
if
(!remove_empty || !new_s.empty())
78
result.push_back(std::move(new_s));
79
80
start=i+1;
81
}
82
}
83
84
// result owns std::strings rather than string_views: see the
85
// comment above the first push_back in the loop.
86
std::string new_s = std::string{s.substr(start, n - start)};
87
88
if
(strip)
89
new_s=
strip_string
(new_s);
90
91
if
(!remove_empty || !new_s.empty())
92
result.push_back(std::move(new_s));
93
94
if
(!remove_empty && result.empty())
95
result.push_back(
""
);
96
}
97
98
void
split_string
(
99
std::string_view s,
100
char
delim,
101
std::string &left,
102
std::string &right,
103
bool
strip)
104
{
105
// delim can't be a space character if using strip
106
PRECONDITION
(!std::isspace(delim) || !strip);
107
108
std::vector<std::string> result =
split_string
(s, delim, strip);
109
110
if
(result.size() != 2)
111
{
112
throw
deserialization_exceptiont
{
113
"expected string '"
+ std::string{s} +
114
"' to contain two substrings "
115
"delimited by "
+
116
delim +
" but has "
+ std::to_string(result.size())};
117
}
118
119
left=result[0];
120
right=result[1];
121
}
122
123
std::vector<std::string>
124
split_string
(std::string_view s,
char
delim,
bool
strip,
bool
remove_empty)
125
{
126
std::vector<std::string> result;
127
split_string
(s, delim, result, strip, remove_empty);
128
return
result;
129
}
130
131
std::string
trim_from_last_delimiter
(std::string_view s,
const
char
delim)
132
{
133
std::string result;
134
const
size_t
index=s.find_last_of(delim);
135
if
(index!=std::string::npos)
136
result=s.substr(0, index);
137
return
result;
138
}
139
140
std::string
escape
(std::string_view s)
141
{
142
std::string result;
143
144
for
(std::size_t i=0; i<s.size(); i++)
145
{
146
if
(s[i]==
'\\'
|| s[i]==
'"'
)
147
result+=
'\\'
;
148
149
result+=s[i];
150
}
151
152
return
result;
153
}
154
155
std::string
escape_non_alnum
(std::string_view to_escape)
156
{
157
std::ostringstream escaped;
158
for
(
auto
&ch : to_escape)
159
{
160
// `ch` may have a negative value in the case of utf-8 encodings of
161
// characters above unicode code point 127. The following line maps these
162
// negative values to positive values in the 128-255 range, using a
163
// `static_cast`. This is neccessary in order to avoid undefined behaviour
164
// in `isalnum`. The positive values are then stored in an integer using a
165
// widening initialisation so that the stream insertion operator prints them
166
// as numbers rather than characters.
167
const
int
uch{
static_cast<
unsigned
char
>
(ch)};
168
if
(ch ==
'_'
)
169
escaped <<
"__"
;
170
else
if
(isalnum(uch))
171
escaped << ch;
172
else
173
escaped <<
'_'
<< std::hex << std::setfill(
'0'
) << std::setw(2) << uch;
174
}
175
return
escaped.str();
176
}
177
178
std::string
capitalize
(std::string_view s)
179
{
180
if
(s.empty())
181
return
std::string{};
182
std::string capitalized = std::string{s};
// copy
183
capitalized[0] = toupper(capitalized[0]);
184
return
capitalized;
185
}
186
187
std::string
wrap_line
(
188
const
std::string &line,
189
const
std::size_t left_margin,
190
const
std::size_t width)
191
{
192
return
wrap_line
(line.cbegin(), line.cend(), left_margin, width);
193
}
194
195
std::string
wrap_line
(
196
std::string::const_iterator left,
197
std::string::const_iterator right,
198
const
std::size_t left_margin,
199
const
std::size_t width)
200
{
201
PRECONDITION
(left_margin < width);
202
203
const
std::size_t column_width = width - left_margin;
204
const
std::string margin(left_margin,
' '
);
205
206
auto
distance = std::distance(left, right);
207
CHECK_RETURN
(distance > 0);
208
209
std::string result;
210
211
if
(
static_cast<
std::size_t
>
(distance) <= column_width)
212
{
213
result.append(margin);
214
result.append(left, right);
215
216
return
result;
217
}
218
219
auto
it_line_begin = left;
220
221
do
222
{
223
// points to the first character past the current column
224
auto
it = it_line_begin + column_width;
225
226
auto
rit_r = std::reverse_iterator<decltype(it)>(it) - 1;
227
auto
rit_l = rit_r + column_width;
228
229
auto
rit_space = std::find(rit_r, rit_l,
' '
);
230
231
if
(rit_space != rit_l)
232
{
233
auto
it_space = rit_space.base() - 1;
234
CHECK_RETURN
(*it_space ==
' '
);
235
236
result.append(margin);
237
result.append(it_line_begin, it_space);
238
result.append(
"\n"
);
239
240
it_line_begin = it_space + 1;
241
}
242
else
243
{
244
// we have not found a space, thus cannot wrap this line
245
result.clear();
246
result.append(left, right);
247
248
return
result;
249
}
250
}
while
(
static_cast<
std::size_t
>
(std::distance(it_line_begin, right)) >
251
column_width);
252
253
result.append(margin);
254
result.append(it_line_begin, right);
255
256
return
result;
257
}
deserialization_exceptiont
Thrown when failing to deserialize a value from some low level format, like JSON or raw bytes.
Definition
exception_utils.h:80
exception_utils.h
invariant.h
CHECK_RETURN
#define CHECK_RETURN(CONDITION)
Definition
invariant.h:495
PRECONDITION
#define PRECONDITION(CONDITION)
Definition
invariant.h:463
INVARIANT
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition
invariant.h:423
split_string
void split_string(std::string_view s, char delim, std::vector< std::string > &result, bool strip, bool remove_empty)
Definition
string_utils.cpp:40
capitalize
std::string capitalize(std::string_view s)
Definition
string_utils.cpp:178
escape_non_alnum
std::string escape_non_alnum(std::string_view to_escape)
Replace non-alphanumeric characters with _xx escapes, where xx are hex digits.
Definition
string_utils.cpp:155
trim_from_last_delimiter
std::string trim_from_last_delimiter(std::string_view s, const char delim)
Definition
string_utils.cpp:131
escape
std::string escape(std::string_view s)
Generic escaping of strings; this is not meant to be a particular programming language.
Definition
string_utils.cpp:140
wrap_line
std::string wrap_line(const std::string &line, const std::size_t left_margin, const std::size_t width)
Wrap line at spaces to not extend past the right margin, and include given padding with spaces to the...
Definition
string_utils.cpp:187
strip_string
std::string strip_string(std::string_view s)
Remove all whitespace characters from either end of a string.
Definition
string_utils.cpp:21
string_utils.h
util
string_utils.cpp
Generated by
1.17.0