XRootD
Loading...
Searching...
No Matches
XrdOucString.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d O u c S t r i n g . h h */
4/* */
5/* (c) 2005 F. Furano (INFN Padova), G. Ganis (CERN) */
6/* */
7/* This file is part of the XRootD software suite. */
8/* */
9/* XRootD is free software: you can redistribute it and/or modify it under */
10/* the terms of the GNU Lesser General Public License as published by the */
11/* Free Software Foundation, either version 3 of the License, or (at your */
12/* option) any later version. */
13/* */
14/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
15/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
16/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
17/* License for more details. */
18/* */
19/* You should have received a copy of the GNU Lesser General Public License */
20/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
21/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
22/* */
23/* The copyright holder's institutional names and contributor's names may not */
24/* be used to endorse or promote products derived from this software without */
25/* specific prior written permission of the institution or contributor. */
26/* All Rights Reserved. See XrdInfo.cc for complete License Terms */
27/******************************************************************************/
28
29#include <cstdio>
30#include <cstring>
31#include <climits>
32
34
35/******************************************************************************/
36/* */
37/* Light string manipulation class */
38/* */
39/******************************************************************************/
40
41#define kMAXINT64LEN 25
42
43#if !defined(WINDOWS)
44//
45// Macro for 'form'-like operations
46#define XOSINTFORM(f,b) \
47 int buf_len = 256; \
48 va_list ap; \
49 va_start(ap, f); \
50again: \
51 b = (char *)realloc(b, buf_len); \
52 int n = vsnprintf(b, buf_len, f, ap); \
53 if (n == -1 || n >= buf_len) { \
54 if (n == -1) \
55 buf_len *= 2; \
56 else \
57 buf_len = n+1; \
58 va_end(ap); \
59 va_start(ap, f); \
60 goto again; \
61 } \
62 va_end(ap);
63// End-Of-Macro for 'form'-like operations
64#endif
65
66// Default blksize for (re-)allocations; active if > 0.
67// Use XrdOucString::setblksize() to activate
68int XrdOucString::blksize = -1;
69
70//________________________________________________________________________
71int XrdOucString::adjust(int ls, int &j, int &k, int nmx)
72{
73 // Check indeces and return effective length
74 // If nmx > 0, indecs are adjusted to get the effective length
75 // smaller than nmx.
76
77 // Check range for beginning
78 j = (j < 0) ? 0 : j;
79 // Check range for end
80 k = (k == -1 || k > (ls-1)) ? (ls-1) : k;
81 // The new length
82 int nlen = k - j + 1;
83 nlen = (nlen > 0) ? nlen : 0;
84 // Check max, if required
85 if (nmx > 0 && nmx < nlen) {
86 k = j + 1 + nmx;
87 nlen = nmx;
88 }
89 // We are done
90 return nlen;
91}
92
93//________________________________________________________________________
94char *XrdOucString::bufalloc(int nsz)
95{
96 // Makes sure that the internal capacity is enough to contain
97 // 'nsz' bytes (including the null-termination).
98 // Buffer is allocated if not yet existing or reallocated if
99 // necessary.
100 // If 'nsz' is negative or null, existing buffer is freed, if any
101 // Returns pointer to buffer.
102
103 char *nstr = 0;
104
105 // New size must be positive; if not, cleanup
106 if (nsz <= 0) {
107 if (str) free(str);
108 init();
109 return nstr;
110 }
111
112 int sz = nsz;
113 // Check the blksize option is activated
114 if (blksize > 1) {
115 int blks = nsz / blksize;
116 sz = (blks+1) * blksize;
117 }
118
119 // Resize, if different from what we have
120 if (sz != siz) {
121 if ((nstr = (char *)realloc(str, sz)))
122 siz = sz;
123 } else
124 // Do nothing
125 nstr = str;
126
127 // We are done
128 return nstr;
129}
130
131//___________________________________________________________________________
132XrdOucString::XrdOucString(const char c, int ls)
133{
134 // Constructor
135 // Create space to store char c as a null-terminated string.
136 // If ls > 0 create space for ls+1 bytes.
137
138 init();
139
140 // If required, allocate the buffer to the requested size
141 if (ls > 0)
142 str = bufalloc(ls+1);
143 else
144 str = bufalloc(2);
145 if (str) {
146 str[0] = c;
147 str[1] = 0;
148 len = 1;
149 }
150}
151
152//___________________________________________________________________________
153XrdOucString::XrdOucString(const char *s, int ls)
154{
155 // Constructor
156 // Create space to store the null terminated string s.
157 // If ls > 0 create space for ls+1 bytes, store the first
158 // ls bytes of s (truncating, if needed), and null-terminate.
159 // This is useful to import non null-terminated string buffers
160 // of known length.
161
162 init();
163
164 // If required, allocate the buffer to the requested size
165 if (ls > 0)
166 str = bufalloc(ls+1);
167 int lr = s ? strlen(s) : 0;
168 if (lr >= 0)
169 assign(s,0,ls-1);
170}
171
172//___________________________________________________________________________
174{
175 // Copy constructor
176
177 init();
178 assign(s.c_str(),0,-1);
179}
180
181//______________________________________________________________________________
182XrdOucString::XrdOucString(const XrdOucString &s, int j, int k, int ls)
183{
184 // Copy constructor (portion of string s: from j to k, inclusive)
185
186 init();
187 // If required, allocate the buffer to the requested size
188 if (ls > 0)
189 str = bufalloc(ls+1);
190
191 int lr = s.length();
192 if (lr > 0) {
193 // Adjust range (to fit in the allocated buffer, if any)
194 if (adjust(lr, j, k, ls) > 0)
195 // assign the string portion
196 assign(s.c_str(),j,k);
197 }
198}
199
200//___________________________________________________________________________
202{
203 // Destructor
204
205 if (str) free(str);
206}
207
208//___________________________________________________________________________
210{
211 // Adopt buffer 'buf'
212
213 if (str) free(str);
214 init();
215 if (buf) {
216 str = buf;
217 len = strlen(buf);
218 siz = len + 1;
219 str = (char *)realloc(str, siz);
220 }
221}
222
223#if !defined(WINDOWS)
224//______________________________________________________________________________
225int XrdOucString::form(const char *fmt, ...)
226{
227 // Recreate the string according to 'fmt' and the arguments
228 // Return -1 in case of failure, or the new length.
229
230 // Decode the arguments
231 XOSINTFORM(fmt, str);
232 siz = buf_len;
233
234 // Re-adjust the length
235 len = strlen(str);
236 str = bufalloc(len+1);
237
238 // Return the new length (in n)
239 return n;
240}
241
242//______________________________________________________________________________
243int XrdOucString::form(XrdOucString &str, const char *fmt, ...)
244{
245 // Format a string in 'str' according to 'fmt' and the arguments
246
247 // Decode the arguments
248 char *buf = 0;
249 XOSINTFORM(fmt, buf);
250
251 // Adopt the new formatted buffer in the string
252 str.setbuffer(buf);
253
254 // Done
255 return n;
256}
257#endif
258
259//______________________________________________________________________________
260int XrdOucString::find(const char c, int start, bool forward)
261{
262 // Find index of first occurence of char c starting from position start
263 // Return index if found, STR_NPOS if not.
264
265 int rc = STR_NPOS;
266
267 // STR_NPOS indicates start from the end
268 if (start == STR_NPOS)
269 start = len - 1;
270
271 // Make sure start makes sense
272 if (start < 0 || start > (len-1))
273 return rc;
274
275 // Now loop
276 int i = start;
277 if (forward) {
278 // forward search
279 for (; i < len; i++) {
280 if (str[i] == c)
281 return i;
282 }
283 } else {
284 // backward search
285 for (; i >= 0; i--) {
286 if (str[i] == c)
287 return i;
288 }
289 }
290
291 // Nothing found
292 return rc;
293}
294
295//______________________________________________________________________________
297{
298 // Find index of first occurence of string s, starting
299 // from position start.
300 // Return index if found, STR_NPOS if not.
301
302 return find((const char *)s.c_str(),start);
303}
304
305//______________________________________________________________________________
306int XrdOucString::find(const char *s, int start)
307{
308 // Find index of first occurence of null-terminated string s, starting
309 // from position start.
310 // Return index if found, STR_NPOS if not.
311
312 int rc = STR_NPOS;
313
314 // Make sure start makes sense
315 if (start < 0 || start > (len-1))
316 return rc;
317
318 // Make sure the string is defined
319 if (!s)
320 return rc;
321
322 // length of substring
323 int ls = strlen(s);
324
325 // if only one meaningful char, use dedicated method
326 if (ls == 1)
327 return find(s[0],start);
328
329 // Make sure that it can fit
330 if (ls > (len-start))
331 return rc;
332
333 // Now loop
334 int i = start;
335 for (; i < len; i++) {
336 if (str[i] == s[0])
337 if (!strncmp(str+i+1,s+1,ls-1))
338 return i;
339 }
340
341 // Nothing found
342 return rc;
343}
344
345//______________________________________________________________________________
347{
348 // Find index of first occurence of string s in backward
349 // direction starting from position start.
350 // If start == STR_NPOS, search starts from end of string (default).
351 // Return index if found, STR_NPOS if not.
352
353 return rfind(s.c_str(),start);
354}
355
356//______________________________________________________________________________
357int XrdOucString::rfind(const char *s, int start)
358{
359 // Find index of first occurence of null-terminated string s in
360 // backwards direction starting from position start.
361 // If start == STR_NPOS, search starts from end of string (default).
362 // Return index if found, STR_NPOS if not.
363
364 int rc = STR_NPOS;
365
366 // STR_NPOS indicates start from the end
367 if (start == STR_NPOS)
368 start = len - 1;
369
370 // Make sure start makes sense
371 if (start < 0 || start > (len-1))
372 return rc;
373
374 // Make sure the string is defined
375 if (!s)
376 return rc;
377
378 // length of substring
379 int ls = strlen(s);
380
381 // if only one meaningful char, use dedicated method
382 if (ls == 1)
383 return find(s[0],start,0);
384
385 // Make sure that it can fit
386 if (ls > len)
387 return rc;
388
389 // Start from the first meaningful position
390 if (ls > (len-start))
391 start = len-ls;
392
393 // Now loop
394 int i = start;
395 for (; i >= 0; i--) {
396 if (str[i] == s[0])
397 if (!strncmp(str+i+1,s+1,ls-1))
398 return i;
399 }
400
401 // Nothing found
402 return rc;
403}
404
405//______________________________________________________________________________
407{
408 // returns 1 if the stored string ends with string s
409
410 return ((len > 0) ? (rfind(c) == (int)(len-1)) : 0);
411}
412
413//______________________________________________________________________________
414bool XrdOucString::endswith(const char *s)
415{
416 // returns 1 if the stored string ends with string s
417
418 int ls = -1;
419 if (s && (ls = (int)strlen(s)) <= len)
420 return ((rfind(s) == (int)(len-strlen(s))) ? 1 : 0);
421
422 return 0;
423}
424
425//___________________________________________________________________________
426int XrdOucString::matches(const char *s, char wch)
427{
428 // Check if local string is compatible with 's' which may
429 // contain wild char wch (default: '*'). For example, if local string
430 // is 'mouse.at.home' the match will be true for 'mouse.*',
431 // and false for 'mouse.*.cinema' .
432 // If does not contain wild characters, this is just a comparison
433 // based on strncmp.
434 // Returns the number of characters matching or 0.
435
436 // Make sure s is defined and we have a local string
437 if (!s || !str)
438 return 0;
439
440 // string size
441 int ls = strlen(s);
442
443 // If no wild card, just make a simple strcmp comparison
444 if (!strchr(s,wch)) {
445 if (!strcmp(str,s))
446 return ls;
447 else
448 return 0;
449 }
450
451 // If s == wch the match is always true
452 if (ls == 1)
453 return 1;
454
455 int rc = 1;
456 // Starting position for the check
457 int cs = 0;
458
459 // token delimiters and size
460 int tb = 0; // begin
461 char *ps = (char *)strchr(s+tb,wch);
462 bool next = 1;
463 while (next) {
464
465 // token end
466 int te = ps ? (ps - s) : ls;
467 // token size
468 int ts = te - tb;
469
470 if (ts) {
471 bool found = 0;
472 while (cs < len) {
473 if (!strncmp(str+cs,s+tb,ts)) {
474 cs += ts;
475 found = 1;
476 break;
477 }
478 cs++;
479 }
480 if (!found) {
481 rc = 0;
482 break;
483 }
484 }
485 // next token begin, if any
486 tb = te + 1;
487 ps = (tb < ls) ? (char *)strchr(s+tb, wch) : 0;
488 next = (ps || (tb < ls)) ? 1 : 0;
489 }
490
491 // If s does not end with a wild card
492 // make sure that everything has been checked
493 if (s[ls-1] != wch && cs < len)
494 rc = 0;
495
496 // The number of chars matching is the number of chars in s
497 // which are not '*'
498 int nm = 0;
499 if (rc > 0) {
500 nm = ls;
501 int n = ls;
502 while (n--) {
503 if (s[n] == wch) nm--;
504 }
505 }
506
507 return nm;
508}
509
510//______________________________________________________________________________
511void XrdOucString::assign(const char *s, int j, int k)
512{
513 // Assign portion of buffer s to local string.
514 // For k == -1 assign all string starting from position j (inclusive).
515 // Use j == 0 and k == -1 to assign the full string.
516
517 int ls = s ? strlen(s) : 0;
518 if (!s) {
519 // We are passed an empty string
520 if (str) {
521 // empty the local string, leaving capacity as it is
522 str[0] = 0;
523 len = 0;
524 }
525 } else {
526 // Adjust range and get length of portion to copy
527 int nlen = adjust(ls, j, k);
528 // Resize, if needed
529 if (nlen > (siz-1))
530 str = bufalloc(nlen+1);
531 if (str) {
532 if (nlen > 0) {
533 strncpy(str,s+j,nlen);
534 str[nlen] = 0;
535 len = nlen;
536 } else {
537 // empty the local string, leaving capacity as it is
538 str[0] = 0;
539 len = 0;
540 }
541 }
542 }
543}
544
545//______________________________________________________________________________
546void XrdOucString::assign(const XrdOucString s, int j, int k)
547{
548 // Assign portion of buffer s to local string.
549
550 assign(s.c_str(),j,k);
551}
552
553//___________________________________________________________________________
554int XrdOucString::keep(int start, int size)
555{
556 // Keep size bytes starting from position start
557 // If size == 0, keep any bytes from start on.
558 // Return number of bytes kept ( <=size )
559
560 int rc = 0;
561
562 // Make sure start makes sense
563 int st = start;
564 if (st < 0 || st > (len-1))
565 return rc;
566
567 // Make sure size makes sense
568 if (size < 0)
569 return rc;
570 int nlen = 0;
571 if (size == 0) {
572 nlen = len - st;
573 } else {
574 nlen = (size > (len - st)) ? (len - st) : size;
575 }
576
577 // Do nothing if all the bytes requested
578 if (nlen >= len)
579 return len;
580
581 // Allocated new string
582 if (nlen > (siz-1))
583 str = bufalloc(nlen+1);
584 if (str) {
585 // Copy the bytes
586 memmove(str,str+st,nlen);
587 // Null terminate
588 str[nlen] = 0;
589 // Assign new string
590 len = nlen;
591 // Return number of bytes kept
592 return nlen;
593 } else
594 return rc;
595}
596
597//___________________________________________________________________________
598void XrdOucString::append(const char *s)
599{
600 // Append string pointed by s to local string.
601 // Memory is reallocated.
602
603 return insert(s);
604}
605
606//___________________________________________________________________________
608{
609 // Append string s to local string.
610 // Memory is reallocated.
611
612 return insert(s);
613}
614
615//___________________________________________________________________________
616void XrdOucString::append(const char c)
617{
618 // Append char c to local string.
619 // Memory is reallocated.
620
621 return insert(c);
622}
623
624//___________________________________________________________________________
625void XrdOucString::append(const int i)
626{
627 // Append string representing integer i to local string.
628
629 return insert(i);
630}
631
632//___________________________________________________________________________
633void XrdOucString::insert(const char *s, int start, int ls)
634{
635 // Insert null-terminated string pointed by s in local string starting
636 // at position start (default append, i.e. start == len).
637 // Memory is reallocated.
638 // If ls > 0, insert only the first ls bytes of s
639
640 // Check start
641 int at = start;
642 at = (at < 0 || at > len) ? len : at;
643
644 if (s) {
645 int lstr = (ls > 0) ? ls : strlen(s);
646 if (str) {
647 int lnew = len + lstr;
648 if (lnew > (siz-1))
649 str = bufalloc(lnew+1);
650 if (str) {
651 // Move the rest of the existing string, if any
652 if (at < len)
653 memmove(str+at+lstr,str+at,(len-at));
654 // Add new string now
655 memcpy(str+at,s,lstr);
656 // Null termination
657 str[lnew] = 0;
658 len = lnew;
659 }
660 } else {
661 if ((str = bufalloc(lstr+1))) {
662 strncpy(str,s,lstr);
663 str[lstr] = 0;
664 len = lstr;
665 }
666 }
667 }
668}
669
670//___________________________________________________________________________
671void XrdOucString::insert(const XrdOucString s, int start)
672{
673 // Insert string s in local string starting at position start (default
674 // append, i.e. start == len).
675
676 return insert(s.c_str(), start);
677}
678
679//___________________________________________________________________________
680void XrdOucString::insert(const char c, int start)
681{
682 // Insert char c in local string starting at position start (default
683 // append, i.e. start == len).
684
685 char sc[2] = {0};
686 sc[0] = c;
687 return insert((const char *)&sc[0], start);
688}
689
690//___________________________________________________________________________
691void XrdOucString::insert(const int i, int start)
692{
693 // Insert string representing integer i in local string starting at
694 // position start (default
695
696 char si[kMAXINT64LEN] = {0};
697 sprintf(si,"%d",i);
698 return insert((const char *)&si[0], start);
699}
700
701//___________________________________________________________________________
702int XrdOucString::replace(const XrdOucString s1, const char *s2, int from, int to)
703{
704 // Replace any occurrence of s1 with s2 from position 'from' to position
705 // 'to' (inclusive).
706 // Return signed size of length modification (in bytes)
707
708 return replace(s1.c_str(),s2,from,to);
709}
710
711//___________________________________________________________________________
712int XrdOucString::replace(const char *s1, const XrdOucString s2, int from, int to)
713{
714 // Replace any occurrence of s1 with s2 from position 'from' to position
715 // 'to' (inclusive).
716 // Return signed size of length modification (in bytes)
717
718 return replace(s1,s2.c_str(),from,to);
719}
720
721//___________________________________________________________________________
723 const XrdOucString s2, int from, int to)
724{
725 // Replace any occurrence of s1 with s2 from position 'from' to position
726 // 'to' (inclusive).
727 // Return signed size of length modification (in bytes)
728
729 return replace(s1.c_str(),s2.c_str(),from,to);
730}
731
732//___________________________________________________________________________
733int XrdOucString::replace(const char *s1, const char *s2, int from, int to)
734{
735 // Replace any occurrence of s1 with s2 from position 'from' to position
736 // 'to' (inclusive).
737 // Return signed size of length modification (in bytes)
738
739 // We must have something to replace
740 if (!str || len <= 0)
741 return 0;
742
743 // The string to replace must be defined and not empty
744 int l1 = s1 ? strlen(s1) : 0;
745 if (l1 <= 0)
746 return 0;
747
748 // Check and adjust indeces
749 if (adjust(len,from,to) <= 0)
750 return 0;
751
752 // length of replacing string
753 int l2 = s2 ? strlen(s2) : 0;
754
755 // If new string is longer we need number of occurencies
756 int nr = 0;
757 if (l1 < l2) {
758 int at = find(s1,from);
759 while (at > -1 && at <= (to-l1+1)) {
760 nr++;
761 at = find(s1,at+l1);
762 }
763 }
764
765 // New size
766 int nlen = (nr > 0) ? (len + nr*(l2-l1)) : len ;
767
768 // Reallocate, if needed
769 if (nlen > (siz-1))
770 str = bufalloc(nlen+1);
771
772 // Now act
773 int dd = l2-l1;
774 int dl = 0;
775 if (str) {
776 if (dd < 0) {
777 int nc = 0;
778 int at = find(s1,from);
779 while (at > -1 && at <= (to-l1+1)) {
780 int atn = find(s1,at+l1);
781 atn = (atn == -1 || atn > (to-l1+1)) ? len : atn;
782 int ln = atn - at - l1;
783 char *pc = str+at+nc*dd;
784 if (l2 > 0)
785 memcpy(pc,s2,l2);
786 if (ln > 0)
787 memmove(pc+l2,str+at+l1,ln);
788 nc++;
789 at = atn;
790 }
791 dl = nc*dd;
792 } else if (dd == 0) {
793 int at = find(s1,from);
794 while (at > -1 && at <= (to-l1+1)) {
795 memcpy(str+at,s2,l2);
796 at = find(s1,at+l1);
797 }
798 } else if (dd > 0) {
799 int nc = nr;
800 int at = rfind(s1,to);
801 int atn = len;
802 while (at > -1 && at >= from) {
803 int ln = atn - at - l1;
804 char *pc = str + at + l1 + nc*dd;
805 if (ln > 0)
806 memmove(pc,str+at+l1,ln);
807 if (l2 > 0)
808 memcpy(pc-l2,s2,l2);
809 nc--;
810 atn = at;
811 if( at - l1 < 0 ) at = -1;
812 else at = rfind(s1,at-l1);
813 }
814 dl = nr*dd;
815 }
816 }
817
818 // Variation of string length
819 len += dl;
820 // Insure null-termination
821 str[len] = 0;
822 // We are done
823 return dl;
824}
825
826//___________________________________________________________________________
827int XrdOucString::erase(int start, int size)
828{
829 // Remove size bytes starting from position start.
830 // If size == 0, remove any bytes from start on.
831 // Return number of bytes removed ( <=size )
832
833 int rc = 0;
834
835 // Make sure start makes sense
836 int st = start;
837 if (st < 0 || st > (len-1))
838 return rc;
839
840 // Make sure size makes sense
841 if (size < 0)
842 return rc;
843 int nrem = 0;
844 if (size == 0) {
845 nrem = len - st;
846 } else {
847 nrem = (size > (len-st)) ? (len-st) : size;
848 }
849 // Do nothing if no byte removal has been requested
850 if (nrem <= 0)
851 return rc;
852 // Calculate new length and allocated new string
853 int nlen = len - nrem;
854 // Copy the remaining bytes, if any
855 if (len-st-nrem)
856 memmove(str+st,str+st+nrem,len-st-nrem);
857 // Null terminate
858 str[nlen] = 0;
859 // Assign new length
860 len = nlen;
861 // Return number of bytes removed
862 return nrem;
863}
864
865//___________________________________________________________________________
866int XrdOucString::erase(const char *s, int from, int to)
867{
868 // Remove any occurence of string s within from and to inclusive.
869 // Use from == 0 and to == -1 to remove all occurences (default).
870 // Return number of bytes removed ( <=size )
871
872 return -replace(s,0,from,to);
873}
874
875//___________________________________________________________________________
876int XrdOucString::erase(XrdOucString s, int from, int to)
877{
878 // Remove any occurence of string s within from and to inclusive.
879 // Use from == 0 and to == -1 to remove all occurences (default).
880 // Return number of bytes removed ( <=size )
881
882 return -replace(s.c_str(),0,from,to);
883}
884
885//___________________________________________________________________________
886void XrdOucString::lower(int start, int size)
887{
888 // Set to lower case size chars starting from position start.
889 // If size == 0, lower all bytes from start on.
890
891 // Make sure start makes sense
892 int st = start;
893 if (st < 0 || st > (len-1))
894 return;
895
896 // Make sure size makes sense
897 if (size < 0)
898 return;
899 int nlw = 0;
900 if (size == 0) {
901 nlw = len - st;
902 } else {
903 nlw = (size > (len-st)) ? (len-st) : size;
904 }
905
906 // Do nothing if no byte removal has been requested
907 if (nlw <= 0)
908 return;
909
910 // Set to lower
911 int i = st;
912 for (; i < st + nlw ; i++ ) {
913 if (str[i] > 0x40 && str[i] < 0x5b)
914 str[i] += 0x20;
915 }
916}
917
918//___________________________________________________________________________
919void XrdOucString::upper(int start, int size)
920{
921 // Set to upper case size chars starting from position start.
922 // If size == 0, upper all bytes from start on.
923
924 // Make sure start makes sense
925 int st = start;
926 if (st < 0 || st > (len-1))
927 return;
928
929 // Make sure size makes sense
930 if (size < 0)
931 return;
932 int nup = 0;
933 if (size == 0) {
934 nup = len - st;
935 } else {
936 nup = (size > (len-st)) ? (len-st) : size;
937 }
938
939 // Do nothing if no byte removal has been requested
940 if (nup <= 0)
941 return;
942
943 // Set to upper
944 int i = st;
945 for (; i < st + nup ; i++ ) {
946 if (str[i] > 0x60 && str[i] < 0x7b)
947 str[i] -= 0x20;
948 }
949}
950
951//___________________________________________________________________________
953{
954 // Reset string making sure to erase completely the information.
955
956 if (str) {
957 volatile char *buf = 0;
958 for (buf = (volatile char *)str; len; buf[--len] = 0) {}
959 len = 0;
960 }
961 len = 0;
962}
963
964//___________________________________________________________________________
965void XrdOucString::reset(const char c, int j, int k)
966{
967 // Reset string making sure to erase completely the information.
968
969 j = (j >= 0 && j < siz) ? j : 0;
970 k = (k >= j && k < siz) ? k : siz-1;
971
972 if (str) {
973 volatile char *buf = (volatile char *)str;
974 int i = j;
975 for (; i <= k; i++)
976 buf[i] = c;
977 }
978 while (str[len-1] == 0)
979 --len;
980}
981
982//______________________________________________________________________________
984{
985 // Assign string representing integer i to local string
986
987 char s[kMAXINT64LEN] = {0};
988 sprintf(s,"%d",i);
989 assign((const char *)&s[0],0,-1);
990 return *this;
991}
992
993//______________________________________________________________________________
995{
996 // Assign char c to local string.
997
998 const char s[] = {c,0};
999 assign(s,0,-1);
1000 return *this;
1001}
1002
1003//______________________________________________________________________________
1005{
1006 // Assign buffer s to local string.
1007
1008 assign(s,0,-1);
1009
1010 return *this;
1011}
1012
1013//______________________________________________________________________________
1015{
1016 // Assign string s to local string.
1017 assign(s.c_str(), 0, -1);
1018
1019 return *this;
1020}
1021
1022//______________________________________________________________________________
1024{
1025 // Return charcater at location i.
1026 static char c = '\0';
1027
1028 if (str) {
1029 if (i > -1 && i < len)
1030 return str[i];
1031 else
1032 abort();
1033 }
1034 return c;
1035}
1036
1037//______________________________________________________________________________
1038XrdOucString operator+(const XrdOucString &s1, const char *s)
1039{
1040 // Return string resulting from concatenation
1041
1042 XrdOucString ns(s1);
1043 if (s && strlen(s))
1044 ns.append(s);
1045 return ns;
1046}
1047
1048//______________________________________________________________________________
1050{
1051 // Return string resulting from concatenation
1052
1053 XrdOucString ns(s1);
1054 if (s.length())
1055 ns.append(s);
1056 return ns;
1057}
1058
1059//______________________________________________________________________________
1060XrdOucString operator+(const XrdOucString &s1, const char c)
1061{
1062 // Return string resulting from concatenation of local string
1063 // and char c
1064
1065 XrdOucString ns(s1);
1066 ns.append(c);
1067 return ns;
1068}
1069
1070//______________________________________________________________________________
1071XrdOucString operator+(const XrdOucString &s1, const int i)
1072{
1073 // Return string resulting from concatenation of local string
1074 // and string representing integer i.
1075
1076 XrdOucString ns(s1);
1077 ns.append(i);
1078 return ns;
1079}
1080
1081//______________________________________________________________________________
1083{
1084 // Add string at s to local string.
1085
1086 if (s && strlen(s))
1087 this->append(s);
1088 return *this;
1089}
1090
1091//______________________________________________________________________________
1093{
1094 // Add string s to local string.
1095
1096 if (s.length())
1097 this->append(s);
1098 return *this;
1099}
1100
1101//______________________________________________________________________________
1103{
1104 // Add char c to local string.
1105
1106 this->append(c);
1107 return *this;
1108}
1109
1110//______________________________________________________________________________
1112{
1113 // Add string representing integer i to local string.
1114
1115 this->append(i);
1116 return *this;
1117}
1118
1119
1120//______________________________________________________________________________
1122{
1123 // Compare string at s to local string: return 1 if matches, 0 if not
1124
1125 if (s && (strlen(s) == (unsigned int)len))
1126 if (!strncmp(str,s,len))
1127 return 1;
1128 return 0;
1129}
1130
1131//______________________________________________________________________________
1133{
1134 // Compare string s to local string: return 1 if matches, 0 if not
1135
1136 if (s.length() == len)
1137 if (!strncmp(str,s.c_str(),len))
1138 return 1;
1139 return 0;
1140}
1141
1142//______________________________________________________________________________
1144{
1145 // Compare char c to local string: return 1 if matches, 0 if not
1146
1147 if (len == 1) {
1148 if (str[0] == c)
1149 return 1;
1150 }
1151 return 0;
1152}
1153
1154//______________________________________________________________________________
1156{
1157 // Compare string representing integer i to local string:
1158 // return 1 if matches, 0 if not
1159
1160 char s[kMAXINT64LEN] = {0};
1161 sprintf(s,"%d",i);
1162 return (*this == ((const char *)&s[0]));
1163}
1164
1165//______________________________________________________________________________
1166std::ostream &operator<< (std::ostream &os, const XrdOucString s)
1167{
1168 // Operator << is useful to print a string into a stream
1169
1170 if (s.c_str())
1171 os << s.c_str();
1172 else
1173 os << "";
1174 return os;
1175}
1176
1177//______________________________________________________________________________
1178XrdOucString const operator+(const char *s1, const XrdOucString s2)
1179{
1180 // Binary operator+
1181 XrdOucString res(s1,s2.length()+strlen(s1));
1182 res.insert(s2);
1183 return res;
1184}
1185
1186//______________________________________________________________________________
1187XrdOucString const operator+(const char c, const XrdOucString s)
1188{
1189 // Binary operator+
1190 XrdOucString res(c,s.length()+1);
1191 res.insert(s);
1192 return res;
1193}
1194
1195//______________________________________________________________________________
1196XrdOucString const operator+(const int i, const XrdOucString s)
1197{
1198 // Binary operator+
1200 res.insert(i);
1201 res.insert(s);
1202 return res;
1203}
1204
1205//______________________________________________________________________________
1207{
1208 // Getter for the block size
1209
1210 return XrdOucString::blksize;
1211}
1212
1213//______________________________________________________________________________
1215{
1216 // Set for the block size
1217
1218 XrdOucString::blksize = bs;
1219}
1220
1221//______________________________________________________________________________
1222int XrdOucString::tokenize(XrdOucString &tok, int from, char del)
1223{
1224 // Search for tokens delimited by 'del' (def ':') in string s; search starts
1225 // from 'from' and the token is returned in 'tok'.
1226 // Returns -1 when there are no more tokens to be analyzed; the length of the
1227 // last valid token, if there are no more delimiters after 'from'; the next
1228 // position after the delimiter, when there are left delimiters in the string.
1229 //
1230 // This method allows to loop over tokens in this way:
1231 //
1232 // XrdOucString myl = "tok1 tok2 tok3";
1233 // char del = ' ';
1234 // XrdOucString tok;
1235 // int from = 1;
1236 // while ((from = myl.tokenize(tok, from, del) != -1) {
1237 // // Analyse tok
1238 // ...
1239 // }
1240 //
1241 // Warning: it may return empty tokens (e.g. in cases like "::"), so
1242 // the token length must always be checked.
1243
1244 // Make sure inputs make sense
1245 if (len <= 0 || from < 0 || from > (len-1))
1246 return -1;
1247
1248 // Find delimiter
1249 int pos = find(del, from);
1250
1251 // Assign to token
1252 if (pos == -1 || pos > from) {
1253 int last = (pos > 0) ? (pos - 1) : -1;
1254 tok.assign(str, from, last);
1255 } else
1256 tok = "";
1257
1258 int next = pos + 1;
1259 if (pos == -1) {
1260 if (tok.length() > 0)
1261 // So we can analize the last one
1262 next = len;
1263 else
1264 next = pos;
1265 }
1266
1267 // return
1268 return next;
1269}
1270
1271//______________________________________________________________________________
1272bool XrdOucString::isdigit(int from, int to)
1273{
1274 // Return true is all chars between from and to (included) are digits
1275
1276 // Make sure inputs make sense
1277 if (len <= 0) return 0;
1278
1279 // Adjust range
1280 if (from < 0 || from > (len-1)) from = 0;
1281 if (to < from) to = len - 1;
1282
1283 char *c = str + from;
1284
1285 // Skip initial '-'
1286 if (*c == '-') c++;
1287
1288 while (c <= str + to) {
1289 if (*c < 48 || *c > 57) return 0;
1290 c++;
1291 }
1292
1293 return 1;
1294}
1295
1296//______________________________________________________________________________
1297long XrdOucString::atoi(int from, int to)
1298{
1299 // Return the long integer corresponding to the number between from and to
1300 // (included), assuming they are digits (check with 'isdigit()').
1301 // Return LONG_MAX in case they are not digits
1302
1303 if (!isdigit(from, to)) return LONG_MAX;
1304
1305 // Adjust range
1306 if (from < 0 || from > (len-1)) from = 0;
1307 if (to < from) to = len - 1;
1308
1309 // Save end char
1310 char e = str[to+1];
1311 str[to+1] = '\0';
1312 long out = strtol(&str[from], 0, 10);
1313 str[to+1] = e;
1314 return out;
1315}
XrdOucString operator+(const XrdOucString &s1, const char *s)
#define kMAXINT64LEN
std::ostream & operator<<(std::ostream &os, const XrdOucString s)
#define XOSINTFORM(f, b)
#define STR_NPOS
void insert(const int i, int start=-1)
void assign(const char *s, int j, int k=-1)
void upper(int pos, int size=0)
char & operator[](int j)
void setbuffer(char *buf)
bool endswith(char c)
int erase(int start=0, int size=0)
static int getblksize()
void reset(const char c, int j=0, int k=-1)
int matches(const char *s, char wch=' *')
int rfind(const char c, int start=STR_NPOS)
XrdOucString & operator+=(const int i)
int replace(const char *s1, const char *s2, int from=0, int to=-1)
int find(const char c, int start=0, bool forward=1)
int length() const
static void setblksize(const int bs)
bool isdigit(int from=0, int to=-1)
long atoi(int from=0, int to=-1)
XrdOucString(int lmx=0)
void append(const int i)
virtual ~XrdOucString()
int form(const char *fmt,...)
int tokenize(XrdOucString &tok, int from, char del=':')
void lower(int pos, int size=0)
XrdOucString & operator=(const int i)
int operator==(const int i)
int keep(int start=0, int size=0)
const char * c_str() const