KaliVeda
Toolkit for HIC analysis
Loading...
Searching...
No Matches
KVString.cpp
1//$Id: KVString.cpp,v 1.15 2008/04/04 13:08:00 franklan Exp $
2
3#include "KVString.h"
4#include "Riostream.h"
5#include "TObjString.h"
6#include "TObjArray.h"
7#include <list>
8#include <stdlib.h>
9#include <ctype.h>
10#include <algorithm>
11
12#include "snprintf.h"
13#include "TBuffer.h"
14#include "TError.h"
15#include "Bytes.h"
16#include "TClass.h"
17#include "TMath.h"
18#include <TObject.h>
19#include <list>
20#include "TRandom.h"
21
22#ifdef R__GLOBALSTL
23namespace std {
24 using::list;
25}
26#endif
28
29
30#ifdef __WITHOUT_TSTRING_TOKENIZE
31
38
39TObjArray* KVString::Tokenize(const TString& delim) const
40{
41 // This function is used to isolate sequential tokens in a TString.
42 // These tokens are separated in the string by at least one of the
43 // characters in delim. The returned array contains the tokens
44 // as TObjString's. The returned array is the owner of the objects,
45 // and must be deleted by the user.
46
47 std::list < Int_t > splitIndex;
48
49 Int_t i, start, nrDiff = 0;
50 for (i = 0; i < delim.Length(); i++) {
51 start = 0;
52 while (start < Length()) {
53 Int_t pos = Index(delim(i), start);
54 if (pos == kNPOS)
55 break;
56 splitIndex.push_back(pos);
57 start = pos + 1;
58 }
59 if (start > 0)
60 nrDiff++;
61 }
62 splitIndex.push_back(Length());
63
64 if (nrDiff > 1)
65 splitIndex.sort();
66
67 TObjArray* arr = new TObjArray();
68 arr->SetOwner();
69
70 start = -1;
71 std::list < Int_t >::const_iterator it;
72#ifndef R__HPUX
73 for (it = splitIndex.begin(); it != splitIndex.end(); it++) {
74#else
75 for (it = splitIndex.begin();
76 it != (std::list < Int_t >::const_iterator) splitIndex.end();
77 it++) {
78#endif
79 Int_t stop = *it;
80 if (stop - 1 >= start + 1) {
81 TString tok = (*this)(start + 1, stop - start - 1);
82 TObjString* objstr = new TObjString(tok);
83 arr->Add(objstr);
84 }
85 start = stop;
86 }
87
88 return arr;
89}
90
91#endif
92
93#ifdef __WITH_KVSTRING_ISDIGIT
94
100
102{
103 // Returns true if all characters in string are digits (0-9) or whitespaces,
104 // i.e. "123456" and "123 456" are both valid integer strings.
105 // Returns false in case string length is 0 or string contains other
106 // characters or only whitespace.
107
108 const char* cp = Data();
109 Ssiz_t len = Length();
110 if (len == 0) return kFALSE;
111 Int_t b = 0, d = 0;
112 for (Ssiz_t i = 0; i < len; ++i) {
113 if (cp[i] != ' ' && !isdigit(cp[i])) return kFALSE;
114 if (cp[i] == ' ') b++;
115 if (isdigit(cp[i])) d++;
116 }
117 if (b && !d)
118 return kFALSE;
119 return kTRUE;
120}
121
122#endif
123
124#ifdef __WITH_KVSTRING_REMOVE
125
129
130KVString& KVString::Remove(TString::EStripType st, char c)
131{
132 // Remove char c at begin and/or end of string (like Strip() but
133 // modifies directly the string.
134 *this = Strip(st, c);
135 return *this;
136}
137
138#endif
139
140#ifdef __WITH_KVSTRING_ATOI
141
146
147Int_t KVString::Atoi() const
148{
149 //Enhanced version of TString::Atoi().
150 //Atoi(): with string="123 456", TString::Atoi() gives value=123
151 // KVString::Atoi() gives value=123456
152
153 Int_t end = Index(" ");
154 //if no whitespaces in string, just use atoi()
155 if (end == -1)
156 return atoi(Data());
157
158 Int_t start = 0;
159 TString tmp;
160 while (end > -1) {
161 tmp += (*this)(start, end - start);
162 start = end + 1;
163 end = Index(" ", start);
164 }
165 end = Length();
166 tmp += (*this)(start, end - start);
167 return atoi(tmp.Data());
168}
169
170#endif
171
172#ifdef __WITH_KVSTRING_ATOF
173
179
181{
182 //Enhanced version of TString::Atof().
183 //Atof(): with string="12,34", TString::Atof() gives value=12
184 // KVString::Atof() gives value=12.34
185
186 //look for a comma and some whitespace
187 Int_t comma = Index(",");
188 Int_t end = Index(" ");
189 //if no commas & no whitespace in string, just use atof()
190 if (comma == -1 && end == -1)
191 return atof(Data());
192 TString tmp = *this;
193 if (comma > -1) {
194 //replace comma with full stop
195 tmp.Replace(comma, 1, ".");
196 }
197 //no whitespace ?
198 if (end == -1)
199 return atof(tmp.Data());
200 //remove whitespace
201 Int_t start = 0;
202 TString tmp2;
203 while (end > -1) {
204 tmp2 += tmp(start, end - start);
205 start = end + 1;
206 end = tmp.Index(" ", start);
207 }
208 end = tmp.Length();
209 tmp2 += tmp(start, end - start);
210 return atof(tmp2.Data());
211}
212
213#endif
214
215#ifdef __WITH_KVSTRING_ISFLOAT
216
227
229{
230 //Returns kTRUE if string contains a floating point or integer number
231 // Examples of valid formats are:
232 // 64320
233 // 64 320
234 // 6 4 3 2 0
235 // 6.4320 6,4320
236 // 6.43e20 6.43E20 6,43e20
237 // 6.43e-20 6.43E-20 6,43e-20
238
239 //we first check if we have an integer, in this case, IsDigit() will be true straight away
240 if (IsDigit()) return kTRUE;
241
242 TString tmp = *this;
243 //now we look for occurrences of '.', ',', e', 'E', '+', '-' and replace each
244 //with ' '. if it is a floating point, IsDigit() will then return kTRUE
245 Int_t i_dot, i_e, i_plus, i_minus, i_comma;
246 i_dot = i_e = i_plus = i_minus = i_comma = -1;
247
248 i_dot = tmp.First('.');
249 if (i_dot > -1) tmp.Replace(i_dot, 1, " ", 1);
250 i_comma = tmp.First(',');
251 if (i_comma > -1) tmp.Replace(i_comma, 1, " ", 1);
252 i_e = tmp.First('e');
253 if (i_e > -1)
254 tmp.Replace(i_e, 1, " ", 1);
255 else {
256 //try for a capital "E"
257 i_e = tmp.First('E');
258 if (i_e > -1) tmp.Replace(i_e, 1, " ", 1);
259 }
260 i_plus = tmp.First('+');
261 if (i_plus > -1) tmp.Replace(i_plus, 1, " ", 1);
262 i_minus = tmp.First('-');
263 if (i_minus > -1) tmp.Replace(i_minus, 1, " ", 1);
264
265 //test if it is now uniquely composed of numbers
266 return tmp.IsDigit();
267}
268
269#endif
270
271
274
276{
277 //Replace every occurence of 'c1' with 'c2'
278 ReplaceAll(&c1, 1, &c2, 1);
279 return (*this);
280}
281
282
283#ifdef __WITH_KVSTRING_ISWHITESPACE
284
287
289{
290 //Returns kTRUE if string is empty (IsNull()) or if every character = ' '
291 return (Length() == CountChar(' '));
292}
293
294#endif
295
296
319
321{
322 //A more strict implementation than the standard 'sscanf'
323 //We require that any characters in the format string which are not format descriptors
324 //("%d" etc.) be identical to the characters in this KVString
325 //
326 //i.e. for a string "file6.root", sscanf("file6.root", "file%d.root", &some_integer) returns 1
327 //but so does sscanf("file6.root", "file%danything_you_want_here_i_dont_care", &some_integer).
328 //
329 //Use this method when you ONLY want "file%d.root" to match "file6.root"
330 //
331 //Returns number of fields read from string
332 //
333 //HANDLED FORMAT DESCRIPTORS
334 //
335 // %d - simple integer descriptor
336 // %3d - simple integer descriptor with length - only integers of correct length accepted
337 // (leading characters may be white space, i.e. ' 4' for 4 written with '%3d')
338 // %03d - simple integer descriptor with length + zero padding - only integers of correct length accepted
339 // (leading characters may be zeroes, i.e. '004' for 4 written with '%03d')
340 // %* - just garbage, no argument required, it is not read. we ignore the rest of the string
341 // and the rest of the format. this is not counted as a field to be read. i.e. Sscanf("%*")
342 // gives 0 for any string, not because it doesn't match, but because there is nothing to read.
343
344 va_list args;
345 va_start(args, fmt);
346
347 Int_t str_index = 0;
348 Int_t read_items = 0;
349 Int_t fmt_index = 0;
350 const char* cp = Data();
351 Int_t int_format_length_descriptor = 0;
352 Bool_t zero_padding = kFALSE;
353
354 while (fmt[fmt_index] != '\0') {
355
356 if (fmt[fmt_index] == '%') {
357 //handle format descriptor
358 fmt_index++;
359 if (fmt[fmt_index] >= '0' && fmt[fmt_index] <= '9') {
360 // case of %nd or %0nd with n=some integer
361 zero_padding = (fmt[fmt_index] == '0');
362 if (zero_padding) fmt_index++;
363 // stick together all figures until 'd' (or some other non-number) is found
364 KVString length_of_number = "";
365 while (fmt[fmt_index] >= '0' && fmt[fmt_index] <= '9') {
366 length_of_number += fmt[fmt_index++];
367 }
368 int_format_length_descriptor = length_of_number.Atoi();
369 }
370 if (fmt[fmt_index] == 'd') {
371 //read an integer
372 KVString dummy;
373 if (int_format_length_descriptor) {
374 if (zero_padding) {
375 // fixed length integer with leading zeroes
376 // i.e. for %03d, '3' will be represented by '003'
377 // we must read int_format_length_descriptor consecutive integers
378 Int_t figures_read = 0;
379 while (cp[str_index] >= '0' && cp[str_index] <= '9') {
380 dummy += cp[str_index++];
381 figures_read++;
382 }
383 if (figures_read != int_format_length_descriptor) {
384 // number is not correct length, string is not good
385 va_end(args);
386 return 0;
387 }
388 else {
389 // good
390 *(va_arg(args, int*)) = dummy.Atoi();
391 fmt_index++;
392 read_items++;
393 }
394 }
395 else {
396 // fixed length integer with white-space padding
397 // i.e. for %3d, '3' will be represented by ' 3'
398 // we must read int_format_length_descriptor consecutive characters
399 // which are either white-space or numbers, at least the last one must
400 // be a number, and once we start reading numbers we cannot have any more
401 // white space
402 Bool_t no_more_whitespace = kFALSE;
403 while (int_format_length_descriptor) {
404 if (cp[str_index] == '\0') {
405 // tried to read past end of string - no good
406 va_end(args);
407 return 0;
408 }
409 if ((cp[str_index] != ' ') && (cp[str_index] < '0' || cp[str_index] > '9')) {
410 // read a non-whitespace non-number - no good
411 va_end(args);
412 return 0;
413 }
414 if ((cp[str_index] == ' ') && no_more_whitespace) {
415 // read a whitespace after starting to read numbers - no good
416 va_end(args);
417 return 0;
418 }
419 if (cp[str_index] != ' ') {
420 no_more_whitespace = kTRUE;
421 dummy += cp[str_index];
422 }
423 str_index++;
424 int_format_length_descriptor--;
425 }
426 // check we read at least one number
427 if (!no_more_whitespace) {
428 va_end(args);
429 return 0;
430 }
431 // check that next character in string is not a number
432 if (cp[str_index + 1] != '\0' && (cp[str_index + 1] < '0' || cp[str_index + 1] > '9')) {
433 va_end(args);
434 return 0;
435 }
436 // good
437 *(va_arg(args, int*)) = dummy.Atoi();
438 fmt_index++;
439 read_items++;
440
441 }
442 }
443 else {
444 // any length of integer i.e. '%d'
445 while (cp[str_index] >= '0' && cp[str_index] <= '9')
446 dummy += cp[str_index++];
447 *(va_arg(args, int*)) = dummy.Atoi();
448 fmt_index++;
449 read_items++;
450 }
451 }
452 else if (fmt[fmt_index] == '*') {
453 //rest of string is garbage
454 va_end(args);
455 return read_items;
456 }
457 }
458 else {
459 //check character in format against string
460 if (fmt[fmt_index] != cp[str_index]) {
461 va_end(args);
462 return 0; //not the same string, return 0
463 }
464 fmt_index++;
465 str_index++;
466 }
467
468
469 }
470
471 va_end(args);
472
473 //if we haven't got to the end of the string, it must not match the format
474 if (cp[str_index] != '\0')
475 return 0;
476
477 return read_items;
478}
479
480
481
482
493
495{
496 // Check if pattern fit the considered string
497 // As in ls shell command the * symbol represents the non discriminant part
498 // of the pattern
499 // if no * is present in the pattern, the result correspond to TString::Contains method
500 // Example KVString st(file_R45.dat);
501 // st.Match("*") -> kTRUE
502 // st.Match("file") ->kTRUE
503 // st.Match("*file*R*") ->kTRUE
504 // etc ....
505 if (!pattern.Contains("*")) return this->Contains(pattern);
506 else if (pattern == "*") return kTRUE;
507 else {
508 std::unique_ptr<TObjArray> tok(pattern.Tokenize("*"));
509 Int_t n_tok = tok->GetEntries();
510 if (!pattern.BeginsWith("*"))
511 if (!BeginsWith(((TObjString*)tok->First())->GetString())) {
512 return kFALSE;
513 }
514 if (!pattern.EndsWith("*"))
515 if (!EndsWith(((TObjString*)tok->Last())->GetString())) {
516 return kFALSE;
517 }
518
519 Int_t idx = 0, num = 0;
520 for (Int_t ii = 0; ii < n_tok; ii += 1) {
521 idx = Index(((TObjString*)tok->At(ii))->GetString(), idx);
522 if (idx != -1) {
523 num += 1;
524 idx++;
525 }
526 else break;
527 }
528 if (num == n_tok) return kTRUE;
529 else return kFALSE;
530 }
531}
532
533
534
564
565void KVString::Begin(TString delim) const
566{
567 // Begin(), Next() and End() can be used to loop over items in
568 // a string separated by the delimiter character given as argument
569 // to Begin().
570 //
571 // Example:
572 //~~~~{.cpp}
573 // KVString str("First | Second | Third");
574 // str.Begin("|");
575 // while( !str.End() ){
576 // cout << str.Next().Data() << endl;
577 // }
578 //~~~~
579 // This will give the following output:
580 //~~~~
581 // First
582 // Second
583 // Third
584 //~~~~
585 // \warning If the delimiter character is not contained in the string,
586 // calling Next() will return the entire contents of the string, after
587 // which End() will return kTRUE. This allows to parse strings containing
588 // variable numbers of parameters separated by a delimiter which is only
589 // used with 2 or more parameters, i.e.:
590 //
591 //~~~~
592 // "par1|par2|par3" -> "par1" "par2" "par3"
593 // "par1" -> "par1"
594 //~~~~
596 fIterIndex = 0;
597 if (IsNull()) {
598 fEndList = kTRUE;
599 kObjArr.reset(nullptr);
600 }
601 else {
602 kObjArr.reset(Tokenize(delim));
603 if (!kObjArr->GetEntries()) {
604 fEndList = kTRUE;
605 kObjArr.reset(nullptr);
606 }
607 }
608}
609
610
611
633
635{
636 // Begin(), Next() and End() can be used to loop over items in
637 // a string separated by the delimiter character given as argument
638 // to Begin().
639 //
640 // Example:
641 //~~~~{.cpp}
642 // KVString str("First | Second | Third");
643 // str.Begin("|");
644 // while( !str.End() ){
645 // cout << str.Next().Data() << endl;
646 // }
647 //~~~~
648 //
649 // This will give the following output:
650 //
651 //~~~~
652 // First
653 // Second
654 // Third
655 //~~~~
656 return fEndList;
657}
658
659
660
694
695KVString KVString::Next(Bool_t strip_whitespace) const
696{
697 // Begin(), Next() and End() can be used to loop over items in
698 // a string separated by the delimiter character given as argument
699 // to Begin().
700 //
701 // @param[in] strip_whitespace if kTRUE (default is kFALSE), any leading or trailing whitespace is removed from each item
702 // \returns next item in string separated by delimiter(s) given to Begin()
703 //
704 // Example:
705 //~~~~{.cpp}
706 // KVString str("First | Second | Third");
707 // str.Begin("|");
708 // while( !str.End() ){
709 // cout << str.Next(kTRUE).Data() << endl;
710 // }
711 //~~~~
712 //
713 // This will give the following output:
714 //
715 //~~~~
716 // First
717 // Second
718 // Third
719 //~~~~
720 //
721 // whereas if Next() is used (i.e. strip_whitespace=kFALSE),
722 // this gives:
723 //
724 //~~~~
725 // First
726 // Second
727 // Third
728 //~~~~
729
730 KVString st;
731 if (!kObjArr.get()) return st;
732 st = ((TObjString*)kObjArr->At(fIterIndex++))->GetString();
733 fEndList = (fIterIndex == kObjArr->GetEntries());
734 if (fEndList) kObjArr.reset(nullptr);
735 if (strip_whitespace) st.Remove(kBoth, ' ');
736 return st;
737}
738
739
740
767
768void KVString::RBegin(TString delim) const
769{
770 // RBegin(), RNext() and End() can be used to loop BACKWARDS over items in
771 // a string separated by the delimiter character given as argument
772 // to RBegin().
773 //
774 // Example:
775 // KVString str("First | Second | Third");
776 // str.RBegin("|");
777 // while( !str.End() ){
778 // cout << str.RNext().Data() << endl;
779 // }
780 //
781 // This will give the following output:
782 //
783 // Third
784 // Second
785 // First
786 //
787 // WARNING: If the delimiter character is not contained in the string,
788 // calling RNext() will return the entire contents of the string, after
789 // which End() will return kTRUE. This allows to parse strings containing
790 // variable numbers of parameters separated by a delimiter which is only
791 // used with 2 or more parameters, i.e.:
792 //
793 // "par1|par2|par3" -> "par3" "par2" "par1"
794 // "par1" -> "par1"
795
797 fIterIndex = 0;
798 if (IsNull()) {
799 fEndList = kTRUE;
800 kObjArr.reset(nullptr);
801 }
802 else {
803 kObjArr.reset(Tokenize(delim));
804 if (!kObjArr->GetEntries()) {
805 fEndList = kTRUE;
806 kObjArr.reset(nullptr);
807 }
808 fIterIndex = kObjArr->GetEntries() - 1;
809 }
810}
811
812
813
840
841KVString KVString::RNext(Bool_t strip_whitespace) const
842{
843 // RBegin(), RNext() and End() can be used to loop BACKWARDS over items in
844 // a string separated by the delimiter character given as argument
845 // to RBegin().
846 // If strip_whitespace=kTRUE (default is kFALSE), any leading or
847 // trailing whitespace is removed from each item.
848 //
849 // Example:
850 // KVString str("First | Second | Third");
851 // str.RBegin("|");
852 // while( !str.End() ){
853 // cout << str.RNext(kTRUE).Data() << endl;
854 // }
855 //
856 // This will give the following output:
857 //
858 // Third
859 // Second
860 // First
861 //
862 // whereas if RNext() is used (i.e. strip_whitespace=kFALSE),
863 // this gives:
864 //
865 // Third
866 // Second
867 // First
868
869 KVString st;
870 if (!kObjArr.get()) return st;
871 st = ((TObjString*)kObjArr->At(fIterIndex--))->GetString();
872 fEndList = (fIterIndex == -1);
873 if (fEndList) kObjArr.reset(nullptr);
874 if (strip_whitespace) st.Remove(kBoth, ' ');
875 return st;
876}
877
878
879
885
887{
888 // Count the number of substrings in this string separated by the given character(s)
889 // e.g. given a string "one | two | three", GetNValues("|") returns 3
890 // Note that if the 'delim' character is not contained in the string,
891 // GetNValues() will return 1 (not 0) - see Begin().
892
893 KVString copy(*this);
894 Int_t nn = 0;
895 copy.Begin(delim);
896 while (!copy.End()) {
897 copy.Next();
898 nn += 1;
899 }
900 return nn;
901}
902
903
904
908
909std::vector<KVString> KVString::Vectorize(TString delim, Bool_t strip_whitespace)
910{
911 // Split string into components according to delimiter 'delim'
912 // See Begin()/Next()/End()
913
914 std::vector<KVString> v;
915 Begin(delim);
916 while (!End()) {
917 v.push_back(Next(strip_whitespace));
918 }
919 return v;
920}
921
922#ifdef __WITH_KVSTRING_ITOA
923
928
930{
931 // Returns true if all characters in string are binary digits (0,1).
932 // Returns false in case string length is 0 or string contains other
933 // characters.
934
935 const char* cp = Data();
936 Ssiz_t len = Length();
937 if (len == 0) return kFALSE;
938 for (Ssiz_t i = 0; i < len; ++i)
939 if (cp[i] != '0' && cp[i] != '1')
940 return kFALSE;
941 return kTRUE;
942}
943
944
945
950
952{
953 // Returns true if all characters in string are octal digits (0-7).
954 // Returns false in case string length is 0 or string contains other
955 // characters.
956
957 const char* cp = Data();
958 Ssiz_t len = Length();
959 if (len == 0) return kFALSE;
960 for (Ssiz_t i = 0; i < len; ++i)
961 if (!isdigit(cp[i]) || cp[i] == '8' || cp[i] == '9')
962 return kFALSE;
963 return kTRUE;
964}
965
966
967
972
974{
975 // Returns true if all characters in string are decimal digits (0-9).
976 // Returns false in case string length is 0 or string contains other
977 // characters.
978
979 const char* cp = Data();
980 Ssiz_t len = Length();
981 if (len == 0) return kFALSE;
982 for (Ssiz_t i = 0; i < len; ++i)
983 if (!isdigit(cp[i]))
984 return kFALSE;
985 return kTRUE;
986}
987
988
989
995
997{
998 // Returns true if all characters in string are expressed in the base
999 // specified (range=2-36), i.e. {0,1} for base 2, {0-9,a-f,A-F} for base 16,
1000 // {0-9,a-z,A-Z} for base 36. Returns false in case string length is 0 or
1001 // string contains other characters.
1002
1003 if (base < 2 || base > 36) {
1004 Error("KVString::IsInBaseN", "base %d is not supported. Suppported bases are {2,3,...,36}.", base);
1005 return kFALSE;
1006 }
1007 if (Length() == 0) {
1008 Error("KVString::IsInBaseN", "input string is empty.") ;
1009 return kFALSE;
1010 }
1011 KVString str = KVString(Data()) ;
1012 str.ToUpper() ;
1013 KVString str_ref0 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
1014 KVString str_ref = str_ref0 ;
1015 str_ref.Remove(base) ;
1016 Bool_t isInBase = kTRUE ;
1017 for (Int_t k = 0; k < str.Length(); k++) {
1018 if (! str_ref.Contains(str[k])) {
1019 isInBase = kFALSE ;
1020 break ;
1021 }
1022 }
1023 return (isInBase);
1024}
1025
1026#endif
1027
1037
1039{
1040 // Converts an Int_t to a KVString with respect to the base specified (2-36).
1041 // Thus it is an enhanced version of sprintf (adapted from versions 0.4 of
1042 // http://www.jb.man.ac.uk/~slowe/cpp/itoa.html).
1043 // Usage: the following statement produce the same output, namely "1111"
1044 // std::cout << KVString::Itoa(15,2) ;
1045 // std::cout << KVString::Itoa(0xF,2) ; /// 0x prefix to handle hex
1046 // std::cout << KVString::Itoa(017,2) ; /// 0 prefix to handle oct
1047 // In case of error returns the "!" string.
1048
1049#ifdef __WITH_KVSTRING_ITOA
1050 std::string buf;
1051 // check that the base if valid
1052 if (base < 2 || base > 36) {
1053 Error("KVString::Itoa", "base %d is not supported. Suppported bases are {2,3,...,36}.", base) ;
1054 return (KVString("!"));
1055 }
1056 buf.reserve(35); // Pre-allocate enough space (35=kMaxDigits)
1057 Int_t quotient = value;
1058 // Translating number to string with base:
1059 do {
1060 buf += "0123456789abcdefghijklmnopqrstuvwxyz"[ TMath::Abs(quotient % base) ];
1061 quotient /= base;
1062 }
1063 while (quotient);
1064 // Append the negative sign
1065 if (value < 0) buf += '-';
1066 std::reverse(buf.begin(), buf.end());
1067 return (KVString(buf.data()));
1068#else
1069 return TString::Itoa(value, base);
1070#endif
1071}
1072
1073
1074
1080
1082{
1083 // Converts a UInt_t (twice the range of an Int_t) to a KVString with respect
1084 // to the base specified (2-36). Thus it is an enhanced version of sprintf
1085 // (adapted from versions 0.4 of http://www.jb.man.ac.uk/~slowe/cpp/itoa.html).
1086 // In case of error returns the "!" string.
1087
1088#ifdef __WITH_KVSTRING_ITOA
1089 std::string buf;
1090 // check that the base if valid
1091 if (base < 2 || base > 36) {
1092 Error("KVString::UItoa", "base %d is not supported. Suppported bases are {2,3,...,36}.", base);
1093 return (KVString("!"));
1094 }
1095 buf.reserve(35); // Pre-allocate enough space (35=kMaxDigits)
1096 UInt_t quotient = value;
1097 // Translating number to string with base:
1098 do {
1099 buf += "0123456789abcdefghijklmnopqrstuvwxyz"[ quotient % base ];
1100 quotient /= base;
1101 }
1102 while (quotient);
1103 std::reverse(buf.begin(), buf.end());
1104 return (KVString(buf.data()));
1105#else
1106 return TString::UItoa(value, base);
1107#endif
1108}
1109
1110
1111
1117
1119{
1120 // Converts a Long64_t to a KVString with respect to the base specified (2-36).
1121 // Thus it is an enhanced version of sprintf (adapted from versions 0.4 of
1122 // http://www.jb.man.ac.uk/~slowe/cpp/itoa.html).
1123 // In case of error returns the "!" string.
1124
1125#ifdef __WITH_KVSTRING_ITOA
1126 std::string buf;
1127 // check that the base if valid
1128 if (base < 2 || base > 36) {
1129 Error("KVString::LLtoa", "base %d is not supported. Suppported bases are {2,3,...,36}.", base);
1130 return (KVString("!"));
1131 }
1132 buf.reserve(35); // Pre-allocate enough space (35=kMaxDigits)
1133 Long64_t quotient = value;
1134 // Translating number to string with base:
1135 do {
1136 buf += "0123456789abcdefghijklmnopqrstuvwxyz"[ TMath::Abs(quotient % base) ];
1137 quotient /= base;
1138 }
1139 while (quotient);
1140 // Append the negative sign
1141 if (value < 0) buf += '-';
1142 std::reverse(buf.begin(), buf.end());
1143 return (KVString(buf.data()));
1144#else
1145 return TString::LLtoa(value, base);
1146#endif
1147}
1148
1149
1150
1156
1158{
1159 // Converts a ULong64_t (twice the range of an Long64_t) to a KVString with
1160 // respect to the base specified (2-36). Thus it is an enhanced version of
1161 // sprintf (adapted from versions 0.4 of http://www.jb.man.ac.uk/~slowe/cpp/itoa.html).
1162 // In case of error returns the "!" string.
1163
1164#ifdef __WITH_KVSTRING_ITOA
1165 std::string buf;
1166 // check that the base if valid
1167 if (base < 2 || base > 36) {
1168 Error("KVString::ULLtoa", "base %d is not supported. Suppported bases are {2,3,...,36}.", base);
1169 return (KVString("!"));
1170 }
1171 buf.reserve(35); // Pre-allocate enough space (35=kMaxDigits)
1172 ULong64_t quotient = value;
1173 // Translating number to string with base:
1174 do {
1175 buf += "0123456789abcdefghijklmnopqrstuvwxyz"[ quotient % base ];
1176 quotient /= base;
1177 }
1178 while (quotient);
1179 std::reverse(buf.begin(), buf.end());
1180 return (KVString(buf.data()));
1181#else
1182 return TString::ULLtoa(value, base);
1183#endif
1184}
1185
1186
1187
1191
1192KVString KVString::BaseConvert(const KVString& s_in, Int_t base_in, Int_t base_out)
1193{
1194 // Converts string from base base_in to base base_out. Supported bases
1195 // are 2-36. At most 64 bit data can be converted.
1196
1197#ifdef __WITH_KVSTRING_ITOA
1198 KVString s_out = "!" ; // return value in case of issue
1199 // checking base range
1200 if (base_in < 2 || base_in > 36 || base_out < 2 || base_out > 36) {
1201 Error("KVString::BaseConvert", "only bases 2-36 are supported (base_in=%d, base_out=%d).", base_in, base_out);
1202 return (s_out);
1203 }
1204 // cleaning s_in
1205 KVString s_in_ = s_in;
1206 Bool_t isSigned = kFALSE;
1207 if (s_in_[0] == '-') {
1208 isSigned = kTRUE;
1209 s_in_.Remove(0, 1);
1210 }
1211 if (!isSigned && s_in_[0] == '+') s_in_.Remove(0, 1); // !isSigned to avoid strings beginning with "-+"
1212 if (base_in == 16 && s_in_.BeginsWith("0x")) s_in_.Remove(0, 2); // removing hex prefix if any
1213 s_in_ = KVString(s_in_.Strip(KVString::kLeading, '0')); // removing leading zeros (necessary for length comparison below)
1214 // checking s_in_ is expressed in the mentionned base
1215 if (!s_in_.IsInBaseN(base_in)) {
1216 Error("KVString::BaseConvert", "s_in=\"%s\" is not in base %d", s_in.Data(), base_in);
1217 return (s_out);
1218 }
1219 // checking s_in <= 64 bits
1220 KVString s_max = KVString::ULLtoa(18446744073709551615ULL, base_in);
1221 if (s_in_.Length() > s_max.Length()) {
1222 // string comparison (s_in_>s_max) does not take care of length
1223 Error("KVString::BaseConvert", "s_in=\"%s\" > %s = 2^64-1 in base %d.", s_in.Data(), s_max.Data(), base_in);
1224 return (s_out);
1225 }
1226 else if (s_in_.Length() == s_max.Length()) {
1227 // if ( s_in_.Length() < s_max.Length() ) everything's fine
1228 s_in_.ToLower(); // s_max is lower case
1229 if (s_in_ > s_max) {
1230 // string comparison
1231 Error("KVString::BaseConvert", "s_in=\"%s\" > %s = 2^64-1 in base %d.", s_in.Data(), s_max.Data(), base_in);
1232 return (s_out);
1233 }
1234 }
1235
1236 // computing s_out
1237 ULong64_t i = ULong64_t(strtoull(s_in.Data(), 0, base_in));
1238 s_out = KVString::ULLtoa(i, base_out);
1239 if (isSigned) s_out.Prepend("-");
1240 return (s_out);
1241#else
1242 return TString::BaseConvert(s_in, base_in, base_out);
1243#endif
1244}
1245
1246
1247
1252
1254{
1255 // Remove any superfluous whitespace (or tabs or newlines) from this string (modifies string)
1256 // i.e. transform " Mary Had\tA Little \n Laaaaaaaaaaaaaaaaaamb"
1257 // into "Mary Had A Little Lamb"
1258
1259 Begin(" \n\t");
1260 KVString tmp;
1261 while (!End()) {
1262 if (tmp.Length()) tmp += " ";
1263 tmp += Next();
1264 }
1265 *this = tmp;
1266}
1267
1268
1269
1274
1276{
1277 // Remove any superfluous whitespace (or tabs or newlines) from string (does not modify string)
1278 // i.e. transform " Mary Had\tA Little \n Laaaaaaaaaaaaaaaaaamb"
1279 // into "Mary Had A Little Lamb"
1280
1281 KVString tmp = *this;
1282 KVString tmp2;
1283 tmp.Begin(" \n\t");
1284 while (!tmp.End()) {
1285 if (tmp2.Length()) tmp2 += " ";
1286 tmp2 += tmp.Next();
1287 }
1288 return tmp2;
1289}
1290
1291
1292
1306
1308{
1309 // list is a collection of objects with names
1310 // this method generates a string containing all characters which appear
1311 // in every name in the list, the others are replaced by the 'bug' character.
1312 //
1313 // example:
1314 // list contains a set of TNamed with names:
1315 // run_0001.root
1316 // run_0002.root
1317 // ...
1318 // run_0099.root
1319 //
1320 // then toto.FindCommonCharacters(list) will produce toto="run_00*.root"
1321
1322 KVString tmp;
1323 TIter next(list);
1324 TObject* o;
1325 // find differences
1326 while ((o = next())) {
1327 if (tmp == "") {
1328 tmp = o->GetName();
1329 continue;
1330 }
1331 int tmplen = tmp.Length();
1332 KVString tmp2 = o->GetName();
1333 int tmp2len = tmp2.Length();
1334 int len = TMath::Min(tmplen, tmp2len);
1335 for (int i = 0; i < len; i++) {
1336 if (tmp[i] != tmp2[i]) tmp[i] = bug;
1337 }
1338 if (tmp2len > tmplen) {
1339 tmp.Append(bug, tmp2len - tmplen);
1340 }
1341 }
1342 // replace multiple occurences of bug
1343 int tmplen = tmp.Length();
1344 *this = "";
1345 bool do_bug = false;
1346 for (int i = 0; i < tmplen; i++) {
1347 if (do_bug) {
1348 if (tmp[i] == bug) continue;
1349 else do_bug = false;
1350 }
1351 else if (tmp[i] == bug) {
1352 do_bug = true;
1353 }
1354 Append(tmp[i]);
1355 }
1356
1357 return *this;
1358}
1359
1360
1361
1362
1376
1378{
1379 // list is a collection of objects with titles
1380 // this method generates a string containing all characters which appear
1381 // in every title in the list, the others are replaced by the 'bug' character.
1382 //
1383 // example:
1384 // list contains a set of TNamed with titles:
1385 // run_0001.root
1386 // run_0002.root
1387 // ...
1388 // run_0099.root
1389 //
1390 // then toto.FindCommonCharacters(list) will produce toto="run_00*.root"
1391
1392 KVString tmp;
1393 TIter next(list);
1394 TObject* o;
1395 // find differences
1396 while ((o = next())) {
1397 if (tmp == "") {
1398 tmp = o->GetTitle();
1399 continue;
1400 }
1401 int tmplen = tmp.Length();
1402 KVString tmp2 = o->GetTitle();
1403 int tmp2len = tmp2.Length();
1404 int len = TMath::Min(tmplen, tmp2len);
1405 for (int i = 0; i < len; i++) {
1406 if (tmp[i] != tmp2[i]) tmp[i] = bug;
1407 }
1408 if (tmp2len > tmplen) {
1409 tmp.Append(bug, tmp2len - tmplen);
1410 }
1411 }
1412 // replace multiple occurences of bug
1413 int tmplen = tmp.Length();
1414 *this = "";
1415 bool do_bug = false;
1416 for (int i = 0; i < tmplen; i++) {
1417 if (do_bug) {
1418 if (tmp[i] == bug) continue;
1419 else do_bug = false;
1420 }
1421 else if (tmp[i] == bug) {
1422 do_bug = true;
1423 }
1424 Append(tmp[i]);
1425 }
1426
1427 return *this;
1428}
1429
1430
1431
1435
1437{
1438 // Generate a random sequence of upper- and lower-case letters
1439 // of given length
1440
1441 Clear();
1442 for (Int_t i = 0; i < length; ++i) {
1443 UInt_t p = gRandom->Integer(52);
1444 if (p < 26) Append((char)p + 'A');
1445 else Append((char)(p - 26) + 'a');
1446 }
1447}
1448
1449
1450
1453
1455{
1456 // Change first character of string from lower to upper case
1457
1458 if ((*this)[0] >= 'a' && (*this)[0] <= 'z')(*this)[0] -= ('a' - 'A');
1459}
1460
1461
1462
1463
1465
1467{
1468 Double_t y = value;
1469 Double_t ey = error;
1470
1471 TString sy = Format("%1.2e", y);
1472 TString sey = Format("%1.1e", ey);
1473
1474 TString sy_dec, sy_exp, sey_dec, sey_exp;
1475 Double_t y_dec, ey_dec;
1476 Int_t y_exp, ey_exp;
1477
1478 //Recup de la valeur y
1479 std::unique_ptr<TObjArray> loa_y(sy.Tokenize("e"));
1480
1481 TIter next_y(loa_y.get());
1482 TObjString* os_y = 0;
1483 os_y = (TObjString*)next_y();
1484 sy_dec = os_y->GetString();
1485 os_y = (TObjString*)next_y();
1486 sy_exp = os_y->GetString();
1487
1488 y_dec = sy_dec.Atof();
1489 y_exp = sy_exp.Atoi();
1490
1491 //Recup de la valeur ey
1492 std::unique_ptr<TObjArray> loa_ey(sey.Tokenize("e"));
1493
1494 TIter next_ey(loa_ey.get());
1495 TObjString* os_ey = 0;
1496
1497 os_ey = (TObjString*)next_ey();
1498 sey_dec = os_ey->GetString();
1499
1500 os_ey = (TObjString*)next_ey();
1501 sey_exp = os_ey->GetString();
1502
1503 ey_dec = sey_dec.Atof();
1504 ey_exp = sey_exp.Atoi();
1505
1506 Double_t err = ey_dec * TMath::Power(10., ey_exp - y_exp);
1507 TString s;
1508
1509 if (!((TString)Format("%1.2g", y_dec)).Contains(".") && err >= 1) {
1510
1511 if (!((TString)Format("%1.2g", err)).Contains(".")) {
1512 if (y_exp == ey_exp) s = Format("%1.2g.0(%g.0).10$^{%d}$", y_dec, ey_dec, y_exp);
1513 else s = Format("%1.3g.0(%g.0).10$^{%d}$", y_dec, err, y_exp);
1514 }
1515 else if (((TString)Format("%1.2g", err)) == ((TString)Format("%1.1g", err)) && ((TString)Format("%1.2g", err)).Contains(".")) {
1516 if (y_exp == ey_exp) s = Format("%1.2g.0(%g0).10$^{%d}$", y_dec, ey_dec, y_exp);
1517 else s = Format("%1.3g.0(%g0).10$^{%d}$", y_dec, err, y_exp);
1518 }
1519 else {
1520 if (y_exp == ey_exp) s = Format("%1.2g.0(%g).10$^{%d}$", y_dec, ey_dec, y_exp);
1521 else s = Format("%1.3g.0(%g).10$^{%d}$", y_dec, err, y_exp);
1522 }
1523 }
1524 else if (((TString)Format("%1.3g", y_dec)) == ((TString)Format("%1.2g", y_dec)) && ((TString)Format("%1.2g", y_dec)).Contains(".") && err < 1) {
1525
1526 if (!((TString)Format("%1.2g", err)).Contains(".")) {
1527 if (y_exp == ey_exp) s = Format("%1.2g0(%g.0).10$^{%d}$", y_dec, ey_dec, y_exp);
1528 else s = Format("%1.3g0(%g.0).10$^{%d}$", y_dec, err, y_exp);
1529 }
1530 else if (((TString)Format("%1.2g", err)) == ((TString)Format("%1.1g", err)) && ((TString)Format("%1.2g", err)).Contains(".")) {
1531 if (y_exp == ey_exp) s = Format("%1.2g0(%g0).10$^{%d}$", y_dec, ey_dec, y_exp);
1532 else s = Format("%1.3g0(%g0).10$^{%d}$", y_dec, err, y_exp);
1533 }
1534 else {
1535 if (y_exp == ey_exp) s = Format("%1.2g0(%g).10$^{%d}$", y_dec, ey_dec, y_exp);
1536 else s = Format("%1.3g0(%g).10$^{%d}$", y_dec, err, y_exp);
1537 }
1538 }
1539 else if (!((TString)Format("%1.2g", err)).Contains(".")) {
1540 if (y_exp == ey_exp) s = Format("%1.2g(%g.0).10$^{%d}$", y_dec, ey_dec, y_exp);
1541 else s = Format("%1.3g(%g.0).10$^{%d}$", y_dec, err, y_exp);
1542 }
1543 else if (((TString)Format("%1.2g", err)) == ((TString)Format("%1.1g", err)) && ((TString)Format("%1.2g", err)).Contains(".")) {
1544 if (y_exp == ey_exp) s = Format("%1.2g(%g0).10$^{%d}$", y_dec, ey_dec, y_exp);
1545 else s = Format("%1.3g(%g0).10$^{%d}$", y_dec, err, y_exp);
1546 }
1547 else {
1548 if (y_exp == ey_exp) s = Format("%1.2g(%g).10$^{%d}$", y_dec, ey_dec, y_exp);
1549 else s = Format("%1.3g(%g).10$^{%d}$", y_dec, err, y_exp);;
1550 }
1551
1552 s.ReplaceAll(".10$^{0}$", "");
1553 s.ReplaceAll("0)", ")");
1554
1555 Form("%s", s.Data());
1556}
1557
1558
int Int_t
unsigned int UInt_t
#define d(i)
bool Bool_t
int Ssiz_t
char Char_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t b
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
R__EXTERN TRandom * gRandom
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition KVString.h:73
void Begin(TString delim) const
Definition KVString.cpp:565
std::unique_ptr< TObjArray > kObjArr
used by Next() to iterate over list
Definition KVString.h:77
void RBegin(TString delim) const
Definition KVString.cpp:768
void RemoveAllExtraWhiteSpace()
Bool_t End() const
Definition KVString.cpp:634
KVString Next(Bool_t strip_whitespace=kFALSE) const
Definition KVString.cpp:695
virtual Int_t Sscanf(const Char_t *fmt,...)
Definition KVString.cpp:320
static KVString ULLtoa(ULong64_t value, Int_t base)
static KVString LLtoa(Long64_t value, Int_t base)
Bool_t fEndList
used by Next() & End() to iterate over list
Definition KVString.h:79
void RandomLetterSequence(Int_t length)
std::vector< KVString > Vectorize(TString delim, Bool_t strip_whitespace=kFALSE)
Definition KVString.cpp:909
KVString()
Definition KVString.h:83
virtual KVString & Substitute(const Char_t c1, const Char_t c2)
Replace every occurence of 'c1' with 'c2'.
Definition KVString.cpp:275
KVString & FindCommonCharacters(const TCollection *, const char bug=' *')
static KVString BaseConvert(const KVString &s_in, Int_t base_in, Int_t base_out)
static KVString UItoa(UInt_t value, Int_t base)
virtual Bool_t Match(TString pattern)
Definition KVString.cpp:494
Int_t GetNValues(TString delim) const
Definition KVString.cpp:886
static KVString Itoa(Int_t value, Int_t base)
KVString RNext(Bool_t strip_whitespace=kFALSE) const
Definition KVString.cpp:841
Int_t fIterIndex
used by Next() to iterate over list
Definition KVString.h:78
KVString & FindCommonTitleCharacters(const TCollection *, const char bug=' *')
KVString StripAllExtraWhiteSpace() const
void Capitalize()
Change first character of string from lower to upper case.
virtual void SetOwner(Bool_t enable=kTRUE)
void Add(TObject *obj) override
const TString & GetString() const
virtual const char * GetName() const
virtual const char * GetTitle() const
virtual UInt_t Integer(UInt_t imax)
static TString UItoa(UInt_t value, Int_t base)
Ssiz_t Length() const
static TString LLtoa(Long64_t value, Int_t base)
Bool_t IsDec() const
void ToLower()
Int_t Atoi() const
static constexpr Ssiz_t kNPOS
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Double_t Atof() const
Bool_t IsFloat() const
void Clear()
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Ssiz_t First(char c) const
const char * Data() const
Bool_t IsDigit() const
Bool_t IsOct() const
TObjArray * Tokenize(const TString &delim) const
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
TString & Append(char c, Ssiz_t rep=1)
Bool_t IsBin() const
Bool_t IsNull() const
static TString BaseConvert(const TString &s_in, Int_t base_in, Int_t base_out)
static TString ULLtoa(ULong64_t value, Int_t base)
Int_t CountChar(Int_t c) const
TString & Prepend(char c, Ssiz_t rep=1)
Bool_t IsInBaseN(Int_t base) const
static TString Format(const char *fmt,...)
static TString Itoa(Int_t value, Int_t base)
Bool_t IsWhitespace() const
void Form(const char *fmt,...)
TString & Remove(EStripType s, char c)
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
TString & ReplaceAll(const char *s1, const char *s2)
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
long long Long64_t
unsigned long long ULong64_t
Double_t y[n]
return c1
Double_t ey[n]
return c2
void Error(const char *location, const char *fmt,...)
start
end
Double_t Min(Double_t a, Double_t b)
Double_t Power(Double_t x, Double_t y)
Double_t Abs(Double_t d)
v
ClassImp(TPyArg)