mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
stringUtils.cpp
Go to the documentation of this file.
1/** \file stringUtils.cpp
2 * \brief Implementation of utilities for working with strings
3 *
4 * \author Jared R. Males (jaredmales@gmail.com)
5 *
6 * \ingroup stringutils
7 *
8 */
9
10//***********************************************************************//
11// Copyright 2020 Jared R. Males (jaredmales@gmail.com)
12//
13// This file is part of mxlib.
14//
15// mxlib is free software: you can redistribute it and/or modify
16// it under the terms of the GNU General Public License as published by
17// the Free Software Foundation, either version 3 of the License, or
18// (at your option) any later version.
19//
20// mxlib is distributed in the hope that it will be useful,
21// but WITHOUT ANY WARRANTY; without even the implied warranty of
22// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23// GNU General Public License for more details.
24//
25// You should have received a copy of the GNU General Public License
26// along with mxlib. If not, see <http://www.gnu.org/licenses/>.
27//***********************************************************************//
28
29#include "../../include/ioutils/stringUtils.hpp"
30
31namespace mx
32{
33namespace ioutils
34{
35
36// Specialization of convertToString to avoid converting a string to a string
37template <>
38std::string convertToString<std::string>( const std::string &value, int precision )
39{
40 static_cast<void>( precision );
41 return value;
42}
43
44namespace stoTImpl
45{
46
47template <typename typeT>
48typeT stoInt32s( const std::string &str, error_t *errc )
49{
50 error_t _errc;
51
52 long val = stoT( str, &_errc, meta::tagT<long>() );
53
54 if( _errc == error_t::noerror )
55 {
56 if( val < std::numeric_limits<typeT>::lowest() )
57 {
58 _errc = error_t::erange;
59 val = std::numeric_limits<typeT>::lowest();
60 }
61 else if( val > std::numeric_limits<typeT>::max() )
62 {
63 _errc = error_t::erange;
64 val = std::numeric_limits<typeT>::max();
65 }
66 }
67
68 if( errc )
69 {
70 *errc = _errc;
71 }
72
73 return static_cast<typeT>( val );
74}
75
76char stoT( const std::string &str, error_t *errc, meta::tagT<char> )
77{
78 return stoInt32s<char>( str, errc );
79}
80
81signed char stoT( const std::string &str, error_t *errc, meta::tagT<signed char> )
82{
83 return stoInt32s<signed char>( str, errc );
84}
85
86unsigned char stoT( const std::string &str, error_t *errc, meta::tagT<unsigned char> )
87{
88 return stoInt32s<unsigned char>( str, errc );
89}
90
91short stoT( const std::string &str, error_t *errc, meta::tagT<short> )
92{
93 return stoInt32s<short>( str, errc );
94}
95
96unsigned short stoT( const std::string &str, error_t *errc, meta::tagT<unsigned short> )
97{
98 return stoInt32s<unsigned short>( str, errc );
99}
100
101int stoT( const std::string &str, error_t *errc, meta::tagT<int> )
102{
103 return stoInt32s<int>( str, errc );
104}
105
106unsigned int stoT( const std::string &str, error_t *errc, meta::tagT<unsigned int> )
107{
108 error_t _errc;
109
110 unsigned long val = stoT( str, &_errc, meta::tagT<unsigned long>() );
111
112 if( _errc == error_t::noerror )
113 {
114 if( val > std::numeric_limits<unsigned int>::max() )
115 {
116 _errc = error_t::erange;
117 val = std::numeric_limits<unsigned int>::max();
118 }
119 }
120
121 if( errc )
122 {
123 *errc = _errc;
124 }
125
126 return static_cast<unsigned int>( val );
127}
128
129long stoT( const std::string &str, error_t *errc, meta::tagT<long> )
130{
131 error_t _errc;
132
133 char *end;
134
135 errno = 0;
136
137 long val = std::strtol( str.c_str(), &end, 10 );
138
139 if( errno != 0 )
140 {
141 _errc = errno2error_t( errno );
142 }
143 else if( end == str.c_str() )
144 {
145 _errc = error_t::invalidarg;
146 }
147 else
148 {
149 _errc = error_t::noerror;
150 }
151
152 if( errc )
153 {
154 *errc = _errc;
155 }
156
157 return val;
158}
159
160unsigned long stoT( const std::string &str, error_t *errc, meta::tagT<unsigned long> )
161{
162 error_t _errc;
163
164 char *end;
165
166 errno = 0;
167
168 unsigned long val = std::strtoul( str.c_str(), &end, 10 );
169
170 if( errno != 0 )
171 {
172 _errc = errno2error_t( errno );
173 }
174 else if( end == str.c_str() )
175 {
176 _errc = error_t::invalidarg;
177 }
178 else
179 {
180 _errc = error_t::noerror;
181 }
182
183 if( errc )
184 {
185 *errc = _errc;
186 }
187
188 return val;
189}
190
191long long stoT( const std::string &str, error_t *errc, meta::tagT<long long> )
192{
193 error_t _errc;
194
195 char *end;
196
197 errno = 0;
198
199 long long val = std::strtoll( str.c_str(), &end, 10 );
200
201 if( errno != 0 )
202 {
203 _errc = errno2error_t( errno );
204 }
205 else if( end == str.c_str() )
206 {
207 _errc = error_t::invalidarg;
208 }
209 else
210 {
211 _errc = error_t::noerror;
212 }
213
214 if( errc )
215 {
216 *errc = _errc;
217 }
218
219 return val;
220}
221
222unsigned long long stoT( const std::string &str, error_t *errc, meta::tagT<unsigned long long> )
223{
224 error_t _errc;
225
226 char *end;
227
228 errno = 0;
229
230 unsigned long long val = std::strtoull( str.c_str(), &end, 10 );
231
232 if( errno != 0 )
233 {
234 _errc = errno2error_t( errno );
235 }
236 else if( end == str.c_str() )
237 {
238 _errc = error_t::invalidarg;
239 }
240 else
241 {
242 _errc = error_t::noerror;
243 }
244
245 if( errc )
246 {
247 *errc = _errc;
248 }
249
250 return val;
251}
252
253/* bool specialization
254 * First looks for 0/1, f/t, or F/T in the first non-space character of str.
255 * Otherwise, uses long long and casts to bool.
256 *
257 * returns the converted numerical value.
258 */
259bool stoT( const std::string &str, error_t *errc, meta::tagT<bool> )
260{
261 char c = str[0];
262 size_t i = 0;
263 while( i < str.length()-1 && isspace( c ) )
264 {
265 ++i;
266 c = str[i];
267 }
268
269 if( c == '0' || c == 'f' || c == 'F' )
270 {
271 if(errc)
272 {
273 *errc = error_t::noerror;
274 }
275
276 return false;
277 }
278 else if( c == '1' || c == 't' || c == 'T' )
279 {
280 if(errc)
281 {
282 *errc = error_t::noerror;
283 }
284
285 return true;
286 }
287
288 return static_cast<bool>( stoT( str, errc, meta::tagT<long long>() ) );
289}
290
291float stoT( const std::string &str, error_t *errc, meta::tagT<float> )
292{
293 error_t _errc;
294
295 char *end;
296
297 errno = 0;
298
299 float val = std::strtof( str.c_str(), &end );
300
301 if( errno != 0 )
302 {
303 _errc = errno2error_t( errno );
304 }
305 else if( end == str.c_str() )
306 {
307 _errc = error_t::invalidarg;
308 }
309 else
310 {
311 _errc = error_t::noerror;
312 }
313
314 if( errc )
315 {
316 *errc = _errc;
317 }
318
319 return val;
320}
321
322double stoT( const std::string &str, error_t *errc, meta::tagT<double> )
323{
324 error_t _errc;
325
326 char *end;
327
328 errno = 0;
329
330 double val = std::strtod( str.c_str(), &end );
331
332 if( errno != 0 )
333 {
334 _errc = errno2error_t( errno );
335 }
336 else if( end == str.c_str() )
337 {
338 _errc = error_t::invalidarg;
339 }
340 else
341 {
342 _errc = error_t::noerror;
343 }
344
345 if( errc )
346 {
347 *errc = _errc;
348 }
349
350 return val;
351}
352
353long double stoT( const std::string &str, error_t *errc, meta::tagT<long double> )
354{
355 error_t _errc;
356
357 char *end;
358
359 errno = 0;
360
361 long double val = std::strtold( str.c_str(), &end );
362
363 if( errno != 0 )
364 {
365 _errc = errno2error_t( errno );
366 }
367 else if( end == str.c_str() )
368 {
369 _errc = error_t::invalidarg;
370 }
371 else
372 {
373 _errc = error_t::noerror;
374 }
375
376 if( errc )
377 {
378 *errc = _errc;
379 }
380
381 return val;
382}
383
384#ifdef HAS_QUAD
385__float128 stoT( const std::string &str, error_t *errc, meta::tagT<__float128> )
386{
387 error_t _errc;
388
389 char *end;
390
391 errno = 0;
392
393 __float128 val = ::strtof128( str.c_str(), &end );
394
395 if( errno != 0 )
396 {
397 _errc = errno2error_t( errno );
398 }
399 else if( end == str.c_str() )
400 {
401 _errc = error_t::invalidarg;
402 }
403 else
404 {
405 _errc = error_t::noerror;
406 }
407
408 if( errc )
409 {
410 *errc = _errc;
411 }
412
413 return val;
414}
415
416#endif // has_quad
417
418std::string stoT( const std::string &str, error_t *errc, meta::tagT<std::string> )
419{
420 if(errc)
421 {
422 *errc = mx::error_t::noerror;
423 }
424
425 return str;
426}
427
428} // namespace stoTImpl
429
430// Convert a string to all lower case.
431mx::error_t toLower( std::string &outstr, const std::string &instr )
432{
433 try
434 {
435 outstr.resize( instr.size() );
436 }
437 catch( const std::length_error &e )
438 {
440 }
441 catch( const std::bad_alloc &e )
442 {
444 }
445 catch( const std::exception &e )
446 {
448 }
449 catch( ... )
450 {
452 }
453
454 for( size_t i = 0; i < instr.size(); ++i )
455 {
456 outstr[i] = tolower( instr[i] );
457 }
458
460}
461
462// Convert a string to all lower case.
463std::string toLower( const std::string &instr, mx::error_t *errc )
464{
465 std::string outstr;
466
467 mx::error_t _errc = toLower( outstr, instr );
468
469 if( errc )
470 {
471 *errc = _errc;
472 }
473
474 return outstr;
475}
476
477// Convert a string to all upper case.
478mx::error_t toUpper( std::string &outstr, const std::string &instr )
479{
480 try
481 {
482 outstr.resize( instr.size() );
483 }
484 catch( const std::length_error &e )
485 {
487 }
488 catch( const std::bad_alloc &e )
489 {
491 }
492 catch( const std::exception &e )
493 {
495 }
496 catch( ... )
497 {
499 }
500
501 for( size_t i = 0; i < instr.size(); ++i )
502 {
503 outstr[i] = toupper( instr[i] );
504 }
505
507}
508
509// Convert a string to all upper case.
510std::string toUpper( const std::string &instr, mx::error_t *errc )
511{
512 std::string outstr;
513
514 mx::error_t _errc = toUpper( outstr, instr );
515
516 if( errc )
517 {
518 *errc = _errc;
519 }
520
521 return outstr;
522}
523
524// Remove all white space from a string.
525void removeWhiteSpace( std::string &outstr, const std::string &instr )
526{
527 outstr = instr;
528
529 outstr.erase( std::remove_if( outstr.begin(), outstr.end(), ::isspace ), outstr.end() );
530}
531
532// Remove all white space from a string.
533std::string removeWhiteSpace( const std::string &instr )
534{
535 std::string outstr;
536
537 removeWhiteSpace( outstr, instr );
538
539 return outstr;
540}
541
542// Wrap a string by breaking it into smaller sized portions of a desired width
543int stringWrap( std::vector<std::string> &lines, const std::string &str, int width )
544{
545 int L = str.length();
546
547 if( L == 0 )
548 return 0;
549 int startPos, tmpPos, endPos;
550
551 bool done = false;
552
553 startPos = 0;
554
555 while( !done )
556 {
557 if( startPos == L )
558 --startPos; // Just to make sure
559
560 endPos = startPos + width;
561
562 if( endPos >= L )
563 {
564 lines.push_back( str.substr( startPos, L - startPos ) );
565 done = true;
566 }
567 else
568 {
569 // Backup to nearest space
570 tmpPos = endPos;
571 while( !isspace( str[tmpPos] ) && tmpPos >= startPos )
572 --tmpPos;
573
574 // If we aren't at the beginning (i.e. splitting consecutive characters) we use new end position
575 if( tmpPos > startPos )
576 endPos = tmpPos;
577
578 lines.push_back( str.substr( startPos, endPos - startPos ) );
579
580 startPos = endPos;
581
582 // Clear 1 space
583 if( str[startPos] == ' ' )
584 ++startPos;
585 }
586 }
587
588 return 0;
589}
590
591} // namespace ioutils
592} // namespace mx
constexpr units::realT c()
The speed of light.
Definition constants.hpp:58
error_t
The mxlib error codes.
Definition error_t.hpp:26
static constexpr error_t errno2error_t(const int &err)
Convert an errno code to error_t.
Definition error_t.hpp:2006
@ noerror
No error has occurred.
@ std_exception
An exception was thrown.
@ exception
An exception was thrown.
@ std_bad_alloc
A bad allocation exception was thrown.
@ erange
Numerical result out of range (ERANGE)
@ invalidarg
An argument was invalid.
@ std_length_error
A length error exception was thrown.
int stringWrap(std::vector< std::string > &lines, const std::string &str, int width)
Wrap a string by breaking it into smaller sized portions of a desired width.
mx::error_t toLower(std::string &outstr, const std::string &instr)
Convert a string to all lower case.
mx::error_t toUpper(std::string &outstr, const std::string &instr)
Convert a string to all upper case.
void removeWhiteSpace(std::string &outstr, const std::string &instr)
Remove all white space from a string.
The mxlib c++ namespace.
Definition mxlib.hpp:37