openPMD-api
StringManip.hpp
1 /* Copyright 2017-2021 Fabian Koller, Franz Poeschel
2  *
3  * This file is part of openPMD-api.
4  *
5  * openPMD-api is free software: you can redistribute it and/or modify
6  * it under the terms of of either the GNU General Public License or
7  * the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * openPMD-api is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License and the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * and the GNU Lesser General Public License along with openPMD-api.
19  * If not, see <http://www.gnu.org/licenses/>.
20  */
21 #pragma once
22 
23 #include <algorithm>
24 #include <iterator>
25 #include <sstream>
26 #include <string>
27 #include <vector>
28 #include <cassert>
29 
30 
31 namespace openPMD
32 {
33 namespace auxiliary
34 {
35 inline bool
36 contains(std::string const &s,
37  std::string const &infix)
38 {
39  return s.find(infix) != std::string::npos;
40 }
41 
42 inline bool
43 contains(std::string const &s,
44  char const infix)
45 {
46  return s.find(infix) != std::string::npos;
47 }
48 
49 inline bool
50 starts_with(std::string const &s,
51  std::string const &prefix)
52 {
53  return (s.size() >= prefix.size()) &&
54  (0 == s.compare(0, prefix.size(), prefix));
55 }
56 
57 inline bool
58 starts_with(std::string const &s,
59  char const prefix)
60 {
61  return !s.empty() &&
62  s[0] == prefix;
63 }
64 
65 inline bool
66 ends_with(std::string const &s,
67  std::string const &suffix)
68 {
69  return (s.size() >= suffix.size()) &&
70  (0 == s.compare(s.size() - suffix.size(), suffix.size(), suffix));
71 }
72 
73 inline bool
74 ends_with(std::string const &s,
75  char const suffix)
76 {
77  return !s.empty() && s.back() == suffix;
78 }
79 
80 inline std::string
81 replace_first(std::string s,
82  std::string const& target,
83  std::string const& replacement)
84 {
85  std::string::size_type pos = s.find(target);
86  if( pos == std::string::npos )
87  return s;
88  s.replace(pos, target.size(), replacement);
89  s.shrink_to_fit();
90 
91  return s;
92 }
93 
94 inline std::string
95 replace_last(std::string s,
96  std::string const& target,
97  std::string const& replacement)
98 {
99  std::string::size_type pos = s.rfind(target);
100  if( pos == std::string::npos )
101  return s;
102  s.replace(pos, target.size(), replacement);
103  s.shrink_to_fit();
104 
105  return s;
106 }
107 
108 inline std::string
109 replace_all_nonrecursively(std::string s,
110  std::string const& target,
111  std::string const& replacement)
112 {
113  std::string::size_type pos = 0;
114  auto tsize = target.size();
115  auto rsize = replacement.size();
116  while (true)
117  {
118  pos = s.find(target, pos);
119  if (pos == std::string::npos)
120  break;
121  s.replace(pos, tsize, replacement);
122  pos += rsize;
123  }
124  s.shrink_to_fit();
125  return s;
126 }
127 
128 inline std::string
129 replace_all(std::string s,
130  std::string const& target,
131  std::string const& replacement)
132 {
133  std::string::size_type pos = 0;
134  auto tsize = target.size();
135  assert(tsize > 0);
136  auto rsize = replacement.size();
137  while (true)
138  {
139  pos = s.find(target, pos);
140  if (pos == std::string::npos)
141  break;
142  s.replace(pos, tsize, replacement);
143  // Allow replacing recursively, but only if
144  // the next replaced substring overlaps with
145  // some parts of the original word.
146  // This avoids loops.
147  pos += rsize - std::min(tsize - 1, rsize);
148  }
149  s.shrink_to_fit();
150  return s;
151 }
152 
153 inline std::vector< std::string >
154 split(std::string const &s,
155  std::string const &delimiter,
156  bool includeDelimiter = false)
157 {
158  std::vector< std::string > ret;
159  std::string::size_type pos, lastPos = 0, length = s.size();
160  while( lastPos < length + 1 )
161  {
162  pos = s.find_first_of(delimiter, lastPos);
163  if( pos == std::string::npos )
164  {
165  pos = length;
166  includeDelimiter = false;
167  }
168 
169  if( pos != lastPos )
170  ret.push_back(s.substr(lastPos, pos + (includeDelimiter ? delimiter.size() : 0) - lastPos));
171 
172  lastPos = pos + 1;
173  }
174 
175  return ret;
176 }
177 
178 inline std::string
179 strip(std::string s, std::vector< char > to_remove)
180 {
181  for( auto const& c : to_remove )
182  s.erase(std::remove(s.begin(), s.end(), c), s.end());
183  s.shrink_to_fit();
184 
185  return s;
186 }
187 
188 template< typename F >
189 std::string
190 trim( std::string const & s, F && to_remove )
191 {
192  auto begin = s.begin();
193  for( ; begin != s.end(); ++begin )
194  {
195  if( !to_remove( *begin ) )
196  {
197  break;
198  }
199  }
200  auto end = s.rbegin();
201  for( ; end != s.rend(); ++end )
202  {
203  if( !to_remove( *end ) )
204  {
205  break;
206  }
207  }
208  return s.substr( begin - s.begin(), end.base() - begin );
209 }
210 
211 inline std::string
212 join(std::vector< std::string > const& vs, std::string const& delimiter)
213 {
214  switch( vs.size() )
215  {
216  case 0:
217  return "";
218  case 1:
219  return vs[0];
220  default:
221  std::ostringstream ss;
222  std::copy(vs.begin(),
223  vs.end() - 1,
224  std::ostream_iterator< std::string >(ss, delimiter.c_str()));
225  ss << *(vs.end() - 1);
226  return ss.str();
227  }
228 }
229 
236 inline std::string
237 removeSlashes( std::string s )
238 {
239  if( auxiliary::starts_with(
240  s,
241  '/'
242  ) )
243  {
244  s = auxiliary::replace_first(
245  s,
246  "/",
247  ""
248  );
249  }
250  if( auxiliary::ends_with(
251  s,
252  '/'
253  ) )
254  {
255  s = auxiliary::replace_last(
256  s,
257  "/",
258  ""
259  );
260  }
261  return s;
262 }
263 
264 } // auxiliary
265 } // openPMD
std::string suffix(Format f)
Determine the default filename suffix for a given storage format.
Definition: Format.cpp:69
Public definitions of openPMD-api.
Definition: Date.cpp:29