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)
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 //___________________________________________________________________________
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 
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 //___________________________________________________________________________
965 void 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 //______________________________________________________________________________
1038 XrdOucString 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 //______________________________________________________________________________
1060 XrdOucString 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 //______________________________________________________________________________
1071 XrdOucString 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 //______________________________________________________________________________
1121 int XrdOucString::operator==(const char *s)
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 //______________________________________________________________________________
1143 int XrdOucString::operator==(const char c)
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 //______________________________________________________________________________
1166 std::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 //______________________________________________________________________________
1178 XrdOucString 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 //______________________________________________________________________________
1187 XrdOucString 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 //______________________________________________________________________________
1196 XrdOucString const operator+(const int i, const XrdOucString s)
1197 {
1198  // Binary operator+
1199  XrdOucString res(s.length()+kMAXINT64LEN);
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 //______________________________________________________________________________
1222 int 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 //______________________________________________________________________________
1272 bool 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 //______________________________________________________________________________
1297 long 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
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