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