Doxygen
Loading...
Searching...
No Matches
stringutil.h
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2024 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16#ifndef STRINGUTIL_H
17#define STRINGUTIL_H
18
19#include <string>
20#include <string_view>
21
22#include "containers.h"
23#include "regex.h"
24
25/** @file
26 * @brief Some helper functions for std::string
27 */
28
29/** Replaces occurrences of substring \a toReplace in string \a s with string \a replaceWith.
30 * Modifies \a s in place.
31 */
32inline void substituteInplace(std::string &s,
33 std::string_view toReplace,std::string_view replaceWith)
34{
35 std::string buf;
36 size_t pos = 0;
37 size_t prevPos = 0;
38 buf.reserve(s.length());
39
40 while ((pos=s.find(toReplace, prevPos))!=std::string::npos)
41 {
42 buf.append(s, prevPos, pos - prevPos);
43 buf += replaceWith;
44 prevPos = pos + toReplace.length();
45 }
46 buf.append(s, prevPos, s.size() - prevPos);
47 s.swap(buf);
48}
49
50/** Returns a new string where occurrences of substring \a toReplace in string \a s are replaced by
51 * string \a replaceWith.
52 */
53inline std::string substituteStringView(std::string_view s,
54 std::string_view toReplace,std::string_view replaceWith)
55{
56 std::string buf;
57 size_t pos = 0;
58 size_t prevPos = 0;
59 buf.reserve(s.length());
60
61 while ((pos=s.find(toReplace, prevPos))!=std::string::npos)
62 {
63 buf.append(s, prevPos, pos - prevPos);
64 buf += replaceWith;
65 prevPos = pos + toReplace.length();
66 }
67 buf.append(s, prevPos, s.size() - prevPos);
68 return buf;
69}
70
71
72/** Given a string view \a s, returns a new, narrower view on that string, skipping over any
73 * leading or trailing whitespace characters.
74 */
75inline std::string_view stripWhiteSpace(std::string_view s)
76{
77 static auto isspace = [](char c){ return c==' ' || c=='\t' || c=='\n' || c=='\r'; };
78 size_t sl = s.length();
79 if (sl==0 || (!isspace(s[0]) && !isspace(s[sl-1]))) return s;
80 size_t start=0, end=sl-1;
81 while (start<sl && isspace(s[start])) start++;
82 if (start==sl) return s.substr(0,0); // only whitespace
83 while (end>start && isspace(s[end])) end--;
84 return s.substr(start,end+1-start);
85}
86
87inline void addTerminalCharIfMissing(std::string &s,char c)
88{
89 if (s.empty())
90 {
91 s+=c;
92 }
93 else
94 {
95 if (s[s.length()-1]!=c) s+=c;
96 }
97}
98
99/// returns true iff \a data points to a substring that matches string literal \a str
100template <size_t N>
101bool literal_at(const char *data,const char (&str)[N])
102{
103 size_t len = N-1; // exclude 0 terminator
104 return data!=nullptr && data[0]==str[0] && dstrncmp(data+1,str+1,len-1)==0;
105}
106
107/// returns true iff \a data points to a substring that matches string literal \a str
108template <size_t N>
109bool literal_at(std::string_view data,const char (&str)[N])
110{
111 size_t len = N-1; // exclude 0 terminator
112 return len<=data.size() && data[0]==str[0] && dstrncmp(data.data()+1,str+1,len-1)==0;
113}
114
115/// split input string \a s by string delimiter \a delimiter.
116/// returns a vector of non-empty strings that are between the delimiters unless
117/// \note If \a retainEmpty is set to true empty strings will added when there
118/// is no content between two 2 subsequent delimiters.
119inline StringVector split(const std::string &s,const std::string &delimiter,bool retainEmpty=false)
120{
121 StringVector result;
122 size_t prev = 0, pos = 0, len = s.length();
123 do
124 {
125 pos = s.find(delimiter, prev);
126 if (pos == std::string::npos)
127 {
128 pos = len;
129 }
130 if (pos>prev)
131 {
132 result.push_back(s.substr(prev,pos-prev));
133 }
134 else if (retainEmpty && pos>0 && pos==prev)
135 {
136 result.push_back("");
137 }
138 prev = pos + delimiter.length();
139 }
140 while (pos<len && prev<len);
141 return result;
142}
143
144/// split input string \a s by regular expression delimiter \a delimiter.
145/// returns a vector of non-empty strings that are between the delimiters
146inline StringVector split(const std::string &s,const reg::Ex &delimiter)
147{
148 StringVector result;
149 reg::Iterator iter(s, delimiter);
151 size_t p=0;
152 for ( ; iter != end; ++iter)
153 {
154 const auto &match = *iter;
155 size_t i=match.position();
156 size_t l=match.length();
157 if (i>p) result.push_back(s.substr(p,i-p));
158 p=i+l;
159 }
160 if (p<s.length()) result.push_back(s.substr(p));
161 return result;
162}
163
164/// create a string where the string in the vector are joined by the given delimiter
165inline std::string join(const StringVector &sv,const std::string &delimiter)
166{
167 std::string result;
168 bool first=true;
169 for (const auto &s : sv)
170 {
171 if (!first) result+=delimiter;
172 first=false;
173 result+=s;
174 }
175 return result;
176}
177
178/// find the index of a string in a vector of strings, returns std::string::npos if the string could not be found
179inline size_t findIndex(const StringVector &sv,const std::string &s)
180{
181 auto it = std::find(sv.begin(),sv.end(),s);
182 return it!=sv.end() ? static_cast<size_t>(it-sv.begin()) : std::string::npos;
183}
184
185/// find the index of the first occurrence of pattern \a re in a string \a s
186/// returns std::string::npos if the pattern could not be found
187inline size_t findIndex(const std::string &s,const reg::Ex &re)
188{
189 reg::Match match;
190 return reg::search(s,match,re) ? static_cast<size_t>(match.position()) : std::string::npos;
191}
192
193inline std::string removeEmptyLines(const std::string &s)
194{
195 std::string out;
196 out.reserve(s.length());
197 const char *p=s.data();
198 if (p)
199 {
200 char c = 0;
201 while ((c=*p++))
202 {
203 if (c=='\n')
204 {
205 const char *e = p;
206 while (*e==' ' || *e=='\t') e++;
207 if (*e=='\n')
208 {
209 p=e;
210 }
211 else out+=c;
212 }
213 else
214 {
215 out+=c;
216 }
217 }
218 }
219 return out;
220}
221
222
223#endif // STRINGUTIL_H
Class representing a regular expression.
Definition regex.h:39
Class to iterate through matches.
Definition regex.h:245
Object representing the matching results.
Definition regex.h:160
std::vector< std::string > StringVector
Definition containers.h:33
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:181
int dstrncmp(const char *str1, const char *str2, size_t len)
Definition dstring.h:56
bool search(std::string_view str, Match &match, const Ex &re, size_t pos)
Search in a given string str starting at position pos for a match against regular expression re.
Definition regex.cpp:850
std::string join(const StringVector &sv, const std::string &delimiter)
create a string where the string in the vector are joined by the given delimiter
Definition stringutil.h:165
std::string substituteStringView(std::string_view s, std::string_view toReplace, std::string_view replaceWith)
Returns a new string where occurrences of substring toReplace in string s are replaced by string repl...
Definition stringutil.h:53
void addTerminalCharIfMissing(std::string &s, char c)
Definition stringutil.h:87
size_t findIndex(const StringVector &sv, const std::string &s)
find the index of a string in a vector of strings, returns std::string::npos if the string could not ...
Definition stringutil.h:179
bool literal_at(const char *data, const char(&str)[N])
returns true iff data points to a substring that matches string literal str
Definition stringutil.h:101
std::string removeEmptyLines(const std::string &s)
Definition stringutil.h:193
void substituteInplace(std::string &s, std::string_view toReplace, std::string_view replaceWith)
Replaces occurrences of substring toReplace in string s with string replaceWith.
Definition stringutil.h:32
std::string_view stripWhiteSpace(std::string_view s)
Given a string view s, returns a new, narrower view on that string, skipping over any leading or trai...
Definition stringutil.h:75
StringVector split(const std::string &s, const std::string &delimiter, bool retainEmpty=false)
split input string s by string delimiter delimiter.
Definition stringutil.h:119