XRootD
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 
33 #include "XrdOuc/XrdOucString.hh"
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); \
50 again: \
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
68 int XrdOucString::blksize = -1;
69 
70 //________________________________________________________________________
71 int 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 //________________________________________________________________________
94 char *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 //___________________________________________________________________________
132 XrdOucString::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 //___________________________________________________________________________
153 XrdOucString::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 //______________________________________________________________________________
182 XrdOucString::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 //___________________________________________________________________________
209 void XrdOucString::setbuffer(char *buf)
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 //______________________________________________________________________________
225 int 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 //______________________________________________________________________________
243 int 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 //______________________________________________________________________________
260 int 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 //______________________________________________________________________________
306 int 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 //______________________________________________________________________________
357 int 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 //______________________________________________________________________________
414 bool 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 //___________________________________________________________________________
426 int 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 //______________________________________________________________________________
511 void 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 //______________________________________________________________________________
546 void 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 //___________________________________________________________________________
554 int 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 //___________________________________________________________________________
598 void 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 //___________________________________________________________________________
616 void 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 //___________________________________________________________________________
625 void XrdOucString::append(const int i)
626 {
627  // Append string representing integer i to local string.
628 
629  return insert(i);
630 }
631 
632 //___________________________________________________________________________
633 void 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 //___________________________________________________________________________
671 void 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 //___________________________________________________________________________
680 void 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 //___________________________________________________________________________
691 void 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 //___________________________________________________________________________
702 int 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 //___________________________________________________________________________
712 int 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 //___________________________________________________________________________
733 int 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 || !s1 || !s2)
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  // Variation of string length
817  len += dl;
818  // Ensure null-termination
819  str[len] = '\0';
820  }
821 
822  // We are done
823  return dl;
824 }
825 
826 //___________________________________________________________________________
827 int 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 //___________________________________________________________________________
866 int 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 //___________________________________________________________________________
876 int 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 //___________________________________________________________________________
886 void 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 //___________________________________________________________________________
919 void 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  if (str)
956  while (len > 0)
957  str[--len] = '\0';
958 
959  len = 0;
960 }
961 
962 //___________________________________________________________________________
963 void XrdOucString::reset(const char c, int j, int k)
964 {
965  // Reset string making sure to erase completely the information.
966 
967  j = (j >= 0 && j < siz) ? j : 0;
968  k = (k >= j && k < siz) ? k : siz-1;
969 
970  if (!str)
971  return;
972 
973  for (int i = j; i <= k; i++)
974  str[i] = c;
975 
976  while (str[len-1] == 0)
977  --len;
978 }
979 
980 //______________________________________________________________________________
982 {
983  // Assign string representing integer i to local string
984 
985  char s[kMAXINT64LEN] = {0};
986  sprintf(s,"%d",i);
987  assign((const char *)&s[0],0,-1);
988  return *this;
989 }
990 
991 //______________________________________________________________________________
993 {
994  // Assign char c to local string.
995 
996  const char s[] = {c,0};
997  assign(s,0,-1);
998  return *this;
999 }
1000 
1001 //______________________________________________________________________________
1003 {
1004  // Assign buffer s to local string.
1005 
1006  assign(s,0,-1);
1007 
1008  return *this;
1009 }
1010 
1011 //______________________________________________________________________________
1013 {
1014  // Assign string s to local string.
1015  assign(s.c_str(), 0, -1);
1016 
1017  return *this;
1018 }
1019 
1020 //______________________________________________________________________________
1022 {
1023  // Return charcater at location i.
1024  static char c = '\0';
1025 
1026  if (str) {
1027  if (i > -1 && i < len)
1028  return str[i];
1029  else
1030  abort();
1031  }
1032  return c;
1033 }
1034 
1035 //______________________________________________________________________________
1036 XrdOucString operator+(const XrdOucString &s1, const char *s)
1037 {
1038  // Return string resulting from concatenation
1039 
1040  XrdOucString ns(s1);
1041  if (s && strlen(s))
1042  ns.append(s);
1043  return ns;
1044 }
1045 
1046 //______________________________________________________________________________
1048 {
1049  // Return string resulting from concatenation
1050 
1051  XrdOucString ns(s1);
1052  if (s.length())
1053  ns.append(s);
1054  return ns;
1055 }
1056 
1057 //______________________________________________________________________________
1058 XrdOucString operator+(const XrdOucString &s1, const char c)
1059 {
1060  // Return string resulting from concatenation of local string
1061  // and char c
1062 
1063  XrdOucString ns(s1);
1064  ns.append(c);
1065  return ns;
1066 }
1067 
1068 //______________________________________________________________________________
1069 XrdOucString operator+(const XrdOucString &s1, const int i)
1070 {
1071  // Return string resulting from concatenation of local string
1072  // and string representing integer i.
1073 
1074  XrdOucString ns(s1);
1075  ns.append(i);
1076  return ns;
1077 }
1078 
1079 //______________________________________________________________________________
1081 {
1082  // Add string at s to local string.
1083 
1084  if (s && strlen(s))
1085  this->append(s);
1086  return *this;
1087 }
1088 
1089 //______________________________________________________________________________
1091 {
1092  // Add string s to local string.
1093 
1094  if (s.length())
1095  this->append(s);
1096  return *this;
1097 }
1098 
1099 //______________________________________________________________________________
1101 {
1102  // Add char c to local string.
1103 
1104  this->append(c);
1105  return *this;
1106 }
1107 
1108 //______________________________________________________________________________
1110 {
1111  // Add string representing integer i to local string.
1112 
1113  this->append(i);
1114  return *this;
1115 }
1116 
1117 
1118 //______________________________________________________________________________
1119 int XrdOucString::operator==(const char *s)
1120 {
1121  // Compare string at s to local string: return 1 if matches, 0 if not
1122 
1123  if (s && (strlen(s) == (unsigned int)len))
1124  if (!strncmp(str,s,len))
1125  return 1;
1126  return 0;
1127 }
1128 
1129 //______________________________________________________________________________
1131 {
1132  // Compare string s to local string: return 1 if matches, 0 if not
1133 
1134  if (s.length() == len)
1135  if (!strncmp(str,s.c_str(),len))
1136  return 1;
1137  return 0;
1138 }
1139 
1140 //______________________________________________________________________________
1141 int XrdOucString::operator==(const char c)
1142 {
1143  // Compare char c to local string: return 1 if matches, 0 if not
1144 
1145  if (len == 1) {
1146  if (str[0] == c)
1147  return 1;
1148  }
1149  return 0;
1150 }
1151 
1152 //______________________________________________________________________________
1154 {
1155  // Compare string representing integer i to local string:
1156  // return 1 if matches, 0 if not
1157 
1158  char s[kMAXINT64LEN] = {0};
1159  sprintf(s,"%d",i);
1160  return (*this == ((const char *)&s[0]));
1161 }
1162 
1163 //______________________________________________________________________________
1164 std::ostream &operator<< (std::ostream &os, const XrdOucString s)
1165 {
1166  // Operator << is useful to print a string into a stream
1167 
1168  if (s.c_str())
1169  os << s.c_str();
1170  else
1171  os << "";
1172  return os;
1173 }
1174 
1175 //______________________________________________________________________________
1176 XrdOucString const operator+(const char *s1, const XrdOucString s2)
1177 {
1178  // Binary operator+
1179  XrdOucString res(s1,s2.length()+strlen(s1));
1180  res.insert(s2);
1181  return res;
1182 }
1183 
1184 //______________________________________________________________________________
1185 XrdOucString const operator+(const char c, const XrdOucString s)
1186 {
1187  // Binary operator+
1188  XrdOucString res(c,s.length()+1);
1189  res.insert(s);
1190  return res;
1191 }
1192 
1193 //______________________________________________________________________________
1194 XrdOucString const operator+(const int i, const XrdOucString s)
1195 {
1196  // Binary operator+
1197  XrdOucString res(s.length()+kMAXINT64LEN);
1198  res.insert(i);
1199  res.insert(s);
1200  return res;
1201 }
1202 
1203 //______________________________________________________________________________
1205 {
1206  // Getter for the block size
1207 
1208  return XrdOucString::blksize;
1209 }
1210 
1211 //______________________________________________________________________________
1213 {
1214  // Set for the block size
1215 
1216  XrdOucString::blksize = bs;
1217 }
1218 
1219 //______________________________________________________________________________
1220 int XrdOucString::tokenize(XrdOucString &tok, int from, char del)
1221 {
1222  // Search for tokens delimited by 'del' (def ':') in string s; search starts
1223  // from 'from' and the token is returned in 'tok'.
1224  // Returns -1 when there are no more tokens to be analyzed; the length of the
1225  // last valid token, if there are no more delimiters after 'from'; the next
1226  // position after the delimiter, when there are left delimiters in the string.
1227  //
1228  // This method allows to loop over tokens in this way:
1229  //
1230  // XrdOucString myl = "tok1 tok2 tok3";
1231  // char del = ' ';
1232  // XrdOucString tok;
1233  // int from = 1;
1234  // while ((from = myl.tokenize(tok, from, del) != -1) {
1235  // // Analyse tok
1236  // ...
1237  // }
1238  //
1239  // Warning: it may return empty tokens (e.g. in cases like "::"), so
1240  // the token length must always be checked.
1241 
1242  // Make sure inputs make sense
1243  if (len <= 0 || from < 0 || from > (len-1))
1244  return -1;
1245 
1246  // Find delimiter
1247  int pos = find(del, from);
1248 
1249  // Assign to token
1250  if (pos == -1 || pos > from) {
1251  int last = (pos > 0) ? (pos - 1) : -1;
1252  tok.assign(str, from, last);
1253  } else
1254  tok = "";
1255 
1256  int next = pos + 1;
1257  if (pos == -1) {
1258  if (tok.length() > 0)
1259  // So we can analize the last one
1260  next = len;
1261  else
1262  next = pos;
1263  }
1264 
1265  // return
1266  return next;
1267 }
1268 
1269 //______________________________________________________________________________
1270 bool XrdOucString::isdigit(int from, int to)
1271 {
1272  // Return true is all chars between from and to (included) are digits
1273 
1274  // Make sure inputs make sense
1275  if (len <= 0) return 0;
1276 
1277  // Adjust range
1278  if (from < 0 || from > (len-1)) from = 0;
1279  if (to < from) to = len - 1;
1280 
1281  char *c = str + from;
1282 
1283  // Skip initial '-'
1284  if (*c == '-') c++;
1285 
1286  while (c <= str + to) {
1287  if (*c < 48 || *c > 57) return 0;
1288  c++;
1289  }
1290 
1291  return 1;
1292 }
1293 
1294 //______________________________________________________________________________
1295 long XrdOucString::atoi(int from, int to)
1296 {
1297  // Return the long integer corresponding to the number between from and to
1298  // (included), assuming they are digits (check with 'isdigit()').
1299  // Return LONG_MAX in case they are not digits
1300 
1301  if (!isdigit(from, to)) return LONG_MAX;
1302 
1303  // Adjust range
1304  if (from < 0 || from > (len-1)) from = 0;
1305  if (to < from) to = len - 1;
1306 
1307  // Save end char
1308  char e = str[to+1];
1309  str[to+1] = '\0';
1310  long out = strtol(&str[from], 0, 10);
1311  str[to+1] = e;
1312  return out;
1313 }
static std::string ts()
timestamp output for logging messages
Definition: XrdCephOss.cc:53
XrdOucString operator+(const XrdOucString &s1, const char *s)
#define kMAXINT64LEN
Definition: XrdOucString.cc:41
#define XOSINTFORM(f, b)
Definition: XrdOucString.cc:46
std::ostream & operator<<(std::ostream &os, const XrdOucString s)
#define STR_NPOS
void insert(const int i, int start=-1)
const char * c_str() const
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)
void hardreset()
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)
static INT to(const char *buffer)
Definition: XrdZipUtils.hh:91