TkN 2.4
Toolkit for Nuclei
Loading...
Searching...
No Matches
tkstring.cpp
1/********************************************************************************
2 * Copyright (c) : Université de Lyon 1, CNRS/IN2P3, UMR5822, *
3 * IP2I, F-69622 Villeurbanne Cedex, France *
4 * Normandie Université, ENSICAEN, UNICAEN, CNRS/IN2P3, *
5 * LPC Caen, F-14000 Caen, France *
6 * Contibutor(s) : *
7 * Jérémie Dudouet jeremie.dudouet@cnrs.fr [2020] *
8 * Diego Gruyer diego.gruyer@cnrs.fr [2020] *
9 * *
10 * Licensed under the MIT License <http://opensource.org/licenses/MIT>. *
11 * SPDX-License-Identifier: MIT *
12 ********************************************************************************/
13#include "tkstring.h"
14
15#include <list>
16#include <cstdarg>
17#include <iostream>
18#include <cmath>
19#include <algorithm>
20#include <iostream>
21
22namespace tkn {
32}
33
34using namespace tkn;
35
37{
38 std::transform(begin(), end(), begin(),[](unsigned char _c){ return std::tolower(_c); });
39 return *this;
40}
41
43{
44 std::transform(begin(), end(), begin(),[](unsigned char _c){ return std::toupper(_c); });
45 return *this;
46}
47
57
59{
60 const char* cp = data();
61 size_t len = length();
62 if (len == 0) return false;
63 int b = 0, d = 0;
64 for (size_t i = 0; i < len; ++i) {
65 if (cp[i] != ' ' && !isdigit(cp[i])) return false;
66 if (cp[i] == ' ') b++;
67 if (isdigit(cp[i])) d++;
68 }
69 return !(b && !d);
70}
71
86
88{
89 //we first check if we have an integer, in this case, IsDigit() will be true straight away
90 if (is_digit()) return true;
91
92 tkstring tmp = *this;
93 //now we look for occurrences of '.', ',', e', 'E', '+', '-' and replace each
94 //with ' '. if it is a floating point, IsDigit() will then return kTRUE
95 int i_dot, i_e, i_plus, i_minus, i_comma;
96
97 i_dot = tmp.index(".");
98 if (i_dot > -1) tmp.replace(i_dot, 1, " ", 1);
99 i_comma = tmp.index(",");
100 if (i_comma > -1) tmp.replace(i_comma, 1, " ", 1);
101 i_e = tmp.index("e");
102 if (i_e > -1)
103 tmp.replace(i_e, 1, " ", 1);
104 else {
105 //try for a capital "E"
106 i_e = tmp.index("E");
107 if (i_e > -1) tmp.replace(i_e, 1, " ", 1);
108 }
109 i_plus = tmp.index("+");
110 if (i_plus > -1) tmp.replace(i_plus, 1, " ", 1);
111 i_minus = tmp.index("-");
112 if (i_minus > -1) tmp.replace(i_minus, 1, " ", 1);
113
114 //test if it is now uniquely composed of numbers
115 return tmp.is_digit();
116}
117
118//tkstring tkstring::energy_to_string(double _val, int _precision)
119//{
120// int exp_value = (_val == 0) ? 0 : 1 + (int)std::floor(std::log10(std::fabs(_val) ) );
121// int exp_error = (_precision == 0) ? 0 : 1 + (int)std::floor(std::log10(std::fabs(_precision) ) );
122
123// std::ostringstream os;
124
125// if(_precision<0) os.precision(exp_value+exp_error);
126// else os.precision(exp_value);
127// os << _val;
128
129// tkstring result = os.str();
130// return result;
131//}
132
133//tkstring tkstring::energy_error_to_string(double _val, int _precision)
134//{
135// int exp_error = (_precision == 0) ? 0 : 1 + (int)std::floor(std::log10(std::fabs(_precision) ) );
136// if(_precision>0) exp_error = 1 + (int)std::floor(std::log10(std::fabs(_val) ) );
137// std::ostringstream os;
138
139// os.precision(exp_error);
140// os << _val;
141
142// tkstring result = os.str();
143// return result;
144//}
145
146
151
152int tkstring::atoi() const
153{
154 int end = index(" ");
155 //if no whitespaces in string, just use atoi()
156 if (end == -1)
157 return std::atoi(data());
158
159 tkstring tmp = *this;
160 tmp.erase(end,1);
161 return std::atoi(tmp.data());
162}
163
168double tkstring::atof() const
169{
170 //look for a comma and some whitespace
171 int comma = index(",");
172 int end = index(" ");
173 //if no commas & no whitespace in string, just use atof()
174 if (comma == -1 && end == -1)
175 return std::atof(data());
176 tkstring tmp = *this;
177 if (comma > -1) {
178 //replace comma with full stop
179 tmp.replace(comma, 1, ".");
180 }
181 //no whitespace ?
182 if (end == -1)
183 return std::atof(tmp.data());
184 //remove whitespace
185 tmp.erase(end,1);
186
187 return std::atof(tmp.data());
188}
189
195size_t tkstring::index(const char *_s, size_t _pos, ECaseCompare _cmp) const
196{
197 if(_cmp == ECaseCompare::kExact) return find(_s,_pos);
198
199 tkstring tmp_copy = *this;
200 tmp_copy.to_lower();
201 tkstring test(_s);
202 test.to_lower();
203 return tmp_copy.find(test,_pos);
204}
205
210
211bool tkstring::equal_to(const char *_s, ECaseCompare _cmp) const
212{
213 if (_cmp == kExact)
214 return strcmp(_s, data()) == 0;
215 return strcasecmp(_s, data()) == 0;
216}
217
218bool tkstring::ends_with(const char *_s, ECaseCompare _cmp) const
219{
220 if (!_s) return true;
221
222 size_t l = strlen(_s);
223 if (l > length()) return false;
224 const char *s2 = data() + length() - l;
225
226 if (_cmp == kExact)
227 return strcmp(_s, s2) == 0;
228 return strcasecmp(_s, s2) == 0;
229}
230
231std::vector<tkstring> tkstring::tokenize(const tkstring &_delim) const
232{
233 std::vector<tkstring> tokens;
234 std::list<int> splitIndex;
235
236 size_t i, start, nrDiff = 0;
237
238 for (i = 0; i < _delim.length(); i++) {
239 start = 0;
240 while (start < length()) {
241 size_t pos = find(_delim.at(i), start);
242 if (pos == npos) break;
243 splitIndex.push_back(pos);
244 start = pos + 1;
245 }
246 if (start > 0) nrDiff++;
247 }
248 splitIndex.push_back(length());
249
250 if (nrDiff > 1)
251 splitIndex.sort();
252
253 start = -1;
254 std::list<int>::const_iterator it;
255#ifndef R__HPUX
256 for (it = splitIndex.begin(); it != splitIndex.end(); ++it) {
257#else
258 for (it = splitIndex.begin(); it != (std::list<int>::const_iterator) splitIndex.end(); ++it) {
259#endif
260 size_t stop = *it;
261 if (stop - 1 >= start + 1) {
262 tkstring tok(substr(start+1, stop-start-1));
263 if(tok.length()) tokens.push_back(tok);
264 }
265 start = stop;
266 }
267
268 return tokens;
269}
270
271std::vector<tkstring> tkstring::tokenize_from_string(const tkstring &_delim) const {
272 std::vector<tkstring> tokens;
273 size_t start = 0, pos = 0;
274
275 // Boucle tant qu'on trouve le délimiteur complet
276 while ((pos = find(_delim, start)) != npos) {
277 tkstring token = substr(start, pos - start);
278 if (token.length()) {
279 tokens.push_back(token);
280 }
281 // On avance de la longueur du délimiteur
282 start = pos + _delim.length();
283 }
284
285 // Ajoute le dernier segment (après le dernier délimiteur)
286 tkstring token = substr(start);
287 if (token.length()) {
288 tokens.push_back(token);
289 }
290
291 return tokens;
292}
293
294tkstring& tkstring::replace_all(const char *_s1, size_t _ls1, const char *_s2, size_t _ls2)
295{
296 if (_s1 && _ls1 > 0) {
297 size_t pos = 0;
298 while ((pos = find(_s1,pos,_ls1)) != npos) {
299 replace(pos, _ls1, _s2, _ls2);
300 pos += _ls2;
301 }
302 }
303 return *this;
304}
305
307{
308 std::size_t found = find_last_of(_s1);
309 tkstring name = substr(found+1);
310
311 return name;
312}
313
315{
316 std::size_t found = find_last_of(_s1);
317 tkstring name = substr(0,found);
318
319 return name;
320}
321
322tkstring tkstring::Form(const char * _format, ...)
323{
324 static char *buffer;
325 static size_t buffer_size;
326
327 va_list argptr;
328 va_start(argptr, _format);
329 size_t length = vsnprintf(buffer, buffer_size, _format, argptr);
330 va_end(argptr);
331
332 if (length + 1 > buffer_size) {
333 buffer_size = length + 1;
334 char *tmp = static_cast<char*>(realloc(buffer, buffer_size));
335 if(tmp) buffer = tmp;
336
337 va_start(argptr, _format);
338 vsnprintf(buffer, buffer_size, _format, argptr);
339 va_end(argptr);
340 }
341
342 tkstring result(buffer);
343
344 return result;
345}
346
348{
349 tkstring temp(*this);
350 return temp;
351}
352
354{
355 for(size_t i=0 ; i<length() ; i++) {
356 if ((*this)[i] >= 'a' && (*this)[i] <= 'z') {
357 (*this)[i] -= ('a' - 'A');
358 return *this;
359 }
360 }
361 return *this;
362}
363
365{
366 tkstring result{};
367
368 const char *cp = data();
369 size_t len = length();
370
371 for (size_t i = 0; i < len; ++i)
372 if (isalpha(cp[i]))
373 result += cp[i];
374 return result;
375}
376
377
379{
380 tkstring result{};
381
382 const char *cp = data();
383 size_t len = length();
384
385 for (size_t i = 0; i < len; ++i)
386 if (!isalpha(cp[i]))
387 result += cp[i];
388 return result;
389}
390
396
398{
399 const char *cp = data();
400 size_t len = length();
401 if (len == 0) return false;
402 for (size_t i = 0; i < len; ++i)
403 if (!isalpha(cp[i]))
404 return false;
405 return true;
406}
407
408const char* tkstring::form(const char * _format, ...)
409{
410 static char *buffer;
411 static size_t buffer_size;
412
413 va_list argptr;
414 va_start(argptr, _format);
415 size_t length = vsnprintf(buffer, buffer_size, _format, argptr);
416 va_end(argptr);
417
418 if (length + 1 > buffer_size) {
419 buffer_size = length + 1;
420 char *tmp = static_cast<char*>(realloc(buffer, buffer_size));
421 if(tmp) buffer = tmp;
422
423 va_start(argptr, _format);
424 vsnprintf(buffer, buffer_size, _format, argptr);
425 va_end(argptr);
426 }
427
428 return buffer;
429}
430
431tkstring::tkstring(double _value, double _error): std::string("")
432{
433 double y = _value;
434 double ey = _error;
435
436 tkstring sy = Form("%1.2e", y);
437 tkstring sey = Form("%1.1e", ey);
438
439 tkstring sy_dec, sy_exp, sey_dec, sey_exp;
440 double y_dec, ey_dec;
441 int y_exp, ey_exp;
442
443 //Recup de la valeur y
444 std::vector<tkstring> loa_y = sy.tokenize("e");
445 sy_dec = loa_y.front();
446 sy_exp = loa_y.back();
447
448 y_dec = sy_dec.atof();
449 y_exp = sy_exp.atoi();
450
451 //Recup de la valeur ey
452 std::vector<tkstring> loa_ey = sey.tokenize("e");
453
454 sey_dec = loa_ey.front();
455 sey_exp = loa_ey.back();
456
457 ey_dec = sey_dec.atof();
458 ey_exp = sey_exp.atoi();
459
460 double err = ey_dec * pow(10., ey_exp - y_exp);
461 tkstring s;
462
463 if (!Form("%1.2g", y_dec).contains(".") && err >= 1) {
464
465 if (!Form("%1.2g", err).contains(".")) {
466 if (y_exp == ey_exp) s = Form("%1.2g.0(%g.0).10$^{%d}$", y_dec, ey_dec, y_exp);
467 else s = Form("%1.3g.0(%g.0).10$^{%d}$", y_dec, err, y_exp);
468 } else if (Form("%1.2g", err) == Form("%1.1g", err) && Form("%1.2g", err).contains(".")) {
469 if (y_exp == ey_exp) s = Form("%1.2g.0(%g0).10$^{%d}$", y_dec, ey_dec, y_exp);
470 else s = Form("%1.3g.0(%g0).10$^{%d}$", y_dec, err, y_exp);
471 } else {
472 if (y_exp == ey_exp) s = Form("%1.2g.0(%g).10$^{%d}$", y_dec, ey_dec, y_exp);
473 else s = Form("%1.3g.0(%g).10$^{%d}$", y_dec, err, y_exp);
474 }
475 } else if (Form("%1.3g", y_dec) == Form("%1.2g", y_dec) && Form("%1.2g", y_dec).contains(".") && err < 1) {
476 if (!Form("%1.2g", err).contains(".")) {
477 if (y_exp == ey_exp) s = Form("%1.2g0(%g.0).10$^{%d}$", y_dec, ey_dec, y_exp);
478 else s = Form("%1.3g0(%g.0).10$^{%d}$", y_dec, err, y_exp);
479 } else if (Form("%1.2g", err) == Form("%1.1g", err) && Form("%1.2g", err).contains(".")) {
480 if (y_exp == ey_exp) s = Form("%1.2g0(%g0).10$^{%d}$", y_dec, ey_dec, y_exp);
481 else s = Form("%1.3g0(%g0).10$^{%d}$", y_dec, err, y_exp);
482 } else {
483 if (y_exp == ey_exp) s = Form("%1.2g0(%g).10$^{%d}$", y_dec, ey_dec, y_exp);
484 else s = Form("%1.3g0(%g).10$^{%d}$", y_dec, err, y_exp);
485 }
486 } else if (!Form("%1.2g", err).contains(".")) {
487 if (y_exp == ey_exp) s = Form("%1.2g(%g.0).10$^{%d}$", y_dec, ey_dec, y_exp);
488 else s = Form("%1.3g(%g.0).10$^{%d}$", y_dec, err, y_exp);
489 } else if (Form("%1.2g", err) == Form("%1.1g", err) && Form("%1.2g", err).contains(".")) {
490 if (y_exp == ey_exp) s = Form("%1.2g(%g0).10$^{%d}$", y_dec, ey_dec, y_exp);
491 else s = Form("%1.3g(%g0).10$^{%d}$", y_dec, err, y_exp);
492 } else {
493 if (y_exp == ey_exp) s = Form("%1.2g(%g).10$^{%d}$", y_dec, ey_dec, y_exp);
494 else s = Form("%1.3g(%g).10$^{%d}$", y_dec, err, y_exp);;
495 }
496
497 s.replace_all(".10$^{0}$", "");
498 s.replace_all("0)", ")");
499
500 *this = s;
501}
502
504{
505 // Remove any superfluous whitespace (or tabs or newlines) from string (modify string)
506 // i.e. transform " Mary Had\tA Little \n Laaaaaaaaaaaaaaaaaamb"
507 // into "Mary Had A Little Lamb"
508
509 tkstring tmp = *this;
510 tkstring tmp2;
511
512 for(const auto &s: tmp.tokenize(" \n\t")) {
513 if (tmp2.length()) tmp2 += " ";
514 tmp2 += s;
515 }
516
517 if(tmp2.begins_with(' ')) tmp2.erase(1);
518
519 *this = tmp2;
520
521 return *this;
522}
523
524int tkstring::count_string(const tkstring &_st) const
525{
526 int count = 0;
527 size_t pos=0;
528
529 while ((pos = find(_st,pos)) != npos) {
530 pos += _st.length();
531 count++;
532 }
533
534 return count;
535}
536
538{
539 // Remove any superfluous whitespace (or tabs or newlines) from string (does not modify string)
540 // i.e. transform " Mary Had\tA Little \n Laaaaaaaaaaaaaaaaaamb"
541 // into "Mary Had A Little Lamb"
542
543 tkstring tmp = *this;
544 tkstring tmp2;
545
546 for(const auto &s: tmp.tokenize(" \n\t")) {
547 if (tmp2.length()) tmp2 += " ";
548 tmp2 += s;
549 }
550
551 if(tmp2.begins_with(' ')) tmp2.erase(1);
552
553 return tmp2;
554}
555
556bool tkstring::match(const char *_pattern) const
557{
558 // Check if pattern fit the considered string
559 // As in ls shell command the * symbol represents the non discriminant part
560 // of the pattern
561 // if no * is present in the pattern, the result correspond to TString::Contains method
562 // Example KVString st(file_R45.dat);
563 // st.Match("*") -> kTRUE
564 // st.Match("file") ->kTRUE
565 // st.Match("*file*R*") ->kTRUE
566 // etc ....
567
568 tkstring pat(_pattern);
569
570 if (!pat.contains("*")) return this->contains(pat);
571 if (pat == "*") return true;
572
573 std::vector<tkstring> tok = pat.tokenize("*");
574 int n_tok = tok.size();
575 if (!pat.begins_with("*"))
576 if (!begins_with(tok.front())) {
577 return false;
578 }
579 if (!pat.ends_with("*"))
580 if (!ends_with(tok.back())) {
581 return false;
582 }
583
584 int idx = 0, num = 0;
585 for (int ii = 0; ii < n_tok; ii += 1) {
586 idx = index(tok.at(ii), idx);
587 if (idx != -1) {
588 num += 1;
589 idx++;
590 } else break;
591 }
592 return (num == n_tok);
593}
594
600std::istream& tkstring::read_line(std::istream& _strm, bool _skip_white)
601{
602 if(_skip_white) getline(_strm >> std::ws, *this);
603 else getline(_strm, *this);
604
605 return _strm;
606}
607
609{
610 if(error.is_empty()) return -1.;
611 return error.atof()*tkstring::get_precision(val);
612}
613
627{
628 double precision = 1.0; int expo; size_t l1,l2;
629
630 l1 = st.index(".",0,tkstring::kIgnoreCase);
631 l2 = st.index("e",0,tkstring::kIgnoreCase);
632
633 if ( l1 == std::string::npos ) { // no point
634 if ( l2 == std::string::npos ) // no exponant
635 precision = 1.0;
636 else { // exponant
637 st.erase(0,l2+1);
638 expo = st.atoi();
639 precision = pow(10.,expo);
640 }
641 } else { // one point
642 if ( l2 == std::string::npos ) { // no exponant
643 expo = - (st.size() - l1 - 1);
644 precision = pow(10.0,expo);
645 }
646 else { // exponant
647 st.erase(0,l2+1);
648 expo = st.atoi();
649 expo = - (l2 - l1 - 1) + expo;
650 precision = pow(10.0,expo);
651 }
652 }
653 if ( precision < 0 ) precision = -1.0 * precision;
654
655 return precision;
656}
657
658#ifdef HAS_ROOT
659ClassImp(tkstring);
660#endif
std::string with usefull tricks from TString (ROOT) and KVString (KaliVeda) and more....
Definition tkstring.h:31
tkstring extract_alpha()
Returns a tkstring composed only of the alphabetic letters of the original tkstring.
Definition tkstring.cpp:364
tkstring strip_all_extra_white_space() const
Definition tkstring.cpp:537
tkstring copy() const
Returns a copy of this string.
Definition tkstring.cpp:347
tkstring & to_lower()
Change all letters to lower case.
Definition tkstring.cpp:36
static const char * form(const char *_format,...)
Definition tkstring.cpp:408
bool is_float() const
Checks if string contains a floating point or integer number.
Definition tkstring.cpp:87
tkstring get_last_occurence(const char *_s1)
Definition tkstring.cpp:306
std::vector< tkstring > tokenize(const tkstring &_delim=" ") const
Create a vector of string separated by at least one delimiter.
Definition tkstring.cpp:231
static tkstring Form(const char *_format,...)
Definition tkstring.cpp:322
tkstring substr(size_type __pos=0, size_type __n=npos) const
Inlines.
Definition tkstring.h:156
std::vector< tkstring > tokenize_from_string(const tkstring &_delim) const
Create a vector of string separated by a full string as delimiter.
Definition tkstring.cpp:271
bool match(const char *_pattern) const
Definition tkstring.cpp:556
bool is_alpha() const
Checks whether tkstring is only composed of alphabetic letters.
Definition tkstring.cpp:397
std::istream & read_line(std::istream &_strm, bool _skip_white=true)
tkstring::read_line
Definition tkstring.cpp:600
int atoi() const
Converts a string to integer value.
Definition tkstring.cpp:152
bool ends_with(const char *_s, ECaseCompare _cmp=kExact) const
Definition tkstring.cpp:218
static double get_absolute_error(tkstring val, tkstring error)
Get absolute uncertainty from value and error strings (1.27 4 -> 0.04), returns -1 in case of empty e...
Definition tkstring.cpp:608
bool equal_to(const char *_s, ECaseCompare _cmp=kExact) const
Returns true if the string and _s are identical.
Definition tkstring.cpp:211
size_t index(const char *_s, size_t _pos=0, ECaseCompare _cmp=kExact) const
Returns the index of the substring _s.
Definition tkstring.cpp:195
tkstring remove_alpha()
Returns a tkstring composed only of the non alphabetic letters of the original tkstring.
Definition tkstring.cpp:378
tkstring & remove_all_extra_white_space()
Definition tkstring.cpp:503
bool contains(const char *_pat, ECaseCompare _cmp=kExact) const
Definition tkstring.h:174
int count_string(const tkstring &_st) const
Definition tkstring.cpp:524
bool begins_with(const char *_s, ECaseCompare _cmp=kExact) const
Definition tkstring.h:162
tkstring & capitalize()
Change first letter of string from lower to upper case.
Definition tkstring.cpp:353
static double get_precision(tkstring _st)
Extract the precision for a given ENSDF data.
Definition tkstring.cpp:626
tkstring & replace_all(const tkstring &_s1, const tkstring &_s2)
Definition tkstring.h:180
bool is_digit() const
Checks if all characters in string are digits (0-9) or whitespaces.
Definition tkstring.cpp:58
tkstring remove_last_occurence(const char *_s1)
Definition tkstring.cpp:314
double atof() const
Converts a string to double value.
Definition tkstring.cpp:168
tkstring & to_upper()
Change all letters to upper case.
Definition tkstring.cpp:42
Definition tklog.cpp:16
tklog & error(tklog &log)
Definition tklog.h:344