LAL  7.5.0.1-08ee4f4
LALString.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2015, 2016 Karl Wette
3 * Copyright (C) 2007 Jolien Creighton
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with with program; see the file COPYING. If not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301 USA
19 */
20 
21 #include <stdarg.h>
22 #include <stdint.h>
23 #include <string.h>
24 #include <lal/LALStdlib.h>
25 #include <lal/LALString.h>
26 
27 /** Like snprintf but doesn't print format truncation warnings with GCC. */
28 int XLALStringPrint(char *s, size_t n, const char *fmt, ...)
29 {
30  int ret;
31  va_list ap;
32  va_start(ap, fmt);
33 #if defined(__GNUC__)
34 #pragma GCC diagnostic push
35 #pragma GCC diagnostic ignored "-Wpragmas"
36 #ifndef __clang__
37 #pragma GCC diagnostic ignored "-Wformat-truncation"
38 #endif
39 #endif
40  ret = vsnprintf(s, n, fmt, ap);
41 #if defined(__GNUC__)
42 #pragma GCC diagnostic pop
43 #endif
44  va_end(ap);
45  return ret;
46 }
47 
48 
49 /** Like strcat but dynamically reallocates string with LALRealloc. */
50 char *XLALStringAppend(char *s, const char *append)
51 {
52  size_t curlen;
53  size_t newlen;
54  if (!append)
55  return s;
56  curlen = s ? strlen(s) : 0;
57  newlen = curlen + strlen(append);
58  s = LALRealloc(s, newlen + 1);
59  if (!s)
61  strcpy(s + curlen, append);
62  return s;
63 }
64 
65 /**
66  * Append the formatted string 'fmt' to the string 's', which
67  * is reallocated with XLALRealloc() to the required size.
68  */
69 char *XLALStringAppendFmt(char *s, const char *fmt, ...)
70 {
71  XLAL_CHECK_NULL(fmt != NULL, XLAL_EFAULT);
72  const size_t n = (s == NULL) ? 0 : strlen(s);
73  va_list ap;
74  va_start(ap, fmt);
75  char tmp[1];
76  const int m = vsnprintf(tmp, sizeof(tmp), fmt, ap);
77  va_end(ap);
78  XLAL_CHECK_NULL(m >= 0, XLAL_ESYS, "vsnprintf('%s', ...) failed", fmt);
79  const size_t l = (n + m + 1) * sizeof(*s);
80  s = XLALRealloc(s, l);
81  XLAL_CHECK_NULL(s != NULL, XLAL_ENOMEM, "XLALRealloc(n=%zu) failed", l);
82  va_start(ap, fmt);
83  XLAL_CHECK_NULL(vsnprintf(s + n, m + 1, fmt, ap) >= 0, XLAL_ESYS, "vsnprintf('%s', ...) failed", fmt);
84  va_end(ap);
85  return s;
86 }
87 
88 /** Like strdup but uses LAL allocation routines (free with LALFree). */
89 char *XLALStringDuplicate(const char *s)
90 {
91  char *dup;
92  dup = XLALStringAppend(NULL, s);
93  return dup;
94 }
95 
96 /**
97  * Copy sources string src to destination string dst.
98  * Up to size - 1 characters are copied and destination string dst is
99  * guaranteed to be NUL-terminated.
100  * Return value is the length of source string src. If this is greater than
101  * or equal to the size of the destination string buffer, size, then truncation
102  * has occurred. Should be nearly equivalent to strlcpy.
103  */
104 size_t XLALStringCopy(char *dst, const char *src, size_t size)
105 {
106  size_t srclen;
107  if (!src)
108  src = "";
109  srclen = strlen(src);
110  if (!dst || size < 1) /* no copy */
111  return srclen;
112  if (size == 1) { /* NUL terminate and exit */
113  dst[0] = 0;
114  return srclen;
115  }
116  strncpy(dst, src, size - 1);
117  dst[size - 1] = 0;
118  return srclen;
119 }
120 
121 /**
122  * Concatenate sources string src to the end of destination string dst.
123  * Characters are added to destination string dst until the source string src
124  * is exhausted or the length of destination string dst is size - 1 characters.
125  * Destination string dst is guaranteed to be NUL-terminated.
126  * Return value is the initial length of destination string dst plus the
127  * length of source string src. If this is greater than
128  * or equal to the size of the destination string buffer, size, then truncation
129  * has occurred. Should be nearly equivalent to strlcat.
130  */
131 size_t XLALStringConcatenate(char *dst, const char *src, size_t size)
132 {
133  size_t srclen;
134  size_t dstlen;
135  if (!src)
136  src = "";
137  srclen = strlen(src);
138  if (!dst || size < 1) /* no copy */
139  return srclen;
140  if (size == 1) { /* NUL terminate and exit */
141  dst[0] = 0;
142  return srclen;
143  }
144  dstlen = strlen(dst);
145  strncat(dst, src, size - dstlen - 1);
146  return srclen + dstlen;
147 }
148 
149 
150 /**
151  * Turn a string in-place into lowercase without using locale-dependent functions.
152  */
153 int XLALStringToLowerCase(char * string)
154 {
155  XLAL_CHECK(string != NULL, XLAL_EINVAL);
156 
157  /* ctype replacements w/o locale */
158  const char upper_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
159  const char lower_chars[] = "abcdefghijklmnopqrstuvwxyz";
160 
161  for (UINT4 i = 0; i < strlen(string); i++) {
162  int c = string[i];
163  if (c) {
164  char *p = strchr(upper_chars, c);
165  if (p) {
166  int offset = p - upper_chars;
167  c = lower_chars[offset];
168  }
169  }
170  string[i] = c;
171 
172  } // for i < len(string)
173 
174  return XLAL_SUCCESS;
175 
176 } /* XLALStringToLowerCase() */
177 
178 
179 /**
180  * Turn a string in-place into uppercase without using locale-dependent functions.
181  */
182 int XLALStringToUpperCase(char * string)
183 {
184  XLAL_CHECK(string != NULL, XLAL_EINVAL);
185 
186  /* ctype replacements w/o locale */
187  const char upper_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
188  const char lower_chars[] = "abcdefghijklmnopqrstuvwxyz";
189 
190  for (UINT4 i = 0; i < strlen(string); i++) {
191  int c = string[i];
192  if (c) {
193  char *p = strchr(lower_chars, c);
194  if (p) {
195  int offset = p - lower_chars;
196  c = upper_chars[offset];
197  }
198  }
199  string[i] = c;
200 
201  } // for i < len(string)
202 
203  return XLAL_SUCCESS;
204 
205 } /* XLALStringToUpperCase() */
206 
207 /**
208  * Compare two strings, ignoring case and without using locale-dependent functions.
209  */
210 int XLALStringCaseCompare(const char *s1, const char *s2)
211 {
212  size_t n = ( (s1 == NULL) ? 0 : strlen(s1) ) + ( (s2 == NULL) ? 0 : strlen(s2) );
213  return XLALStringNCaseCompare(s1, s2, n);
214 }
215 
216 /**
217  * Compare the first N characters of two strings, ignoring case and without using locale-dependent functions.
218  */
219 int XLALStringNCaseCompare(const char *s1, const char *s2, size_t n)
220 {
221 
222  /* ctype replacements w/o locale */
223  const char upper_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
224  const char lower_chars[] = "abcdefghijklmnopqrstuvwxyz";
225 
226  int c1 = 0, c2 = 0;
227 
228  /* based on implementation of strncmp() in glibc */
229  while (n-- > 0) {
230 
231  c1 = (s1 == NULL) ? 0 : *s1++;
232  c2 = (s2 == NULL) ? 0 : *s2++;
233 
234  /* convert c1 to lower case */
235  if (c1) {
236  char *p = strchr(upper_chars, c1);
237  if (p) {
238  int offset = p - upper_chars;
239  c1 = lower_chars[offset];
240  }
241  }
242 
243  /* convert c2 to lower case */
244  if (c2) {
245  char *p = strchr(upper_chars, c2);
246  if (p) {
247  int offset = p - upper_chars;
248  c2 = lower_chars[offset];
249  }
250  }
251 
252  /* compare characters */
253  if (c1 == '\0' || c1 != c2) {
254  return c1 - c2;
255  }
256 
257  }
258 
259  return c1 - c2;
260 
261 }
262 
263 /**
264  * Locates substring needle in string haystack, ignoring case and without
265  * using locale-dependent functions.
266  */
267 char * XLALStringCaseSubstring(const char *haystack, const char *needle)
268 {
269  size_t haystack_length;
270  size_t needle_length = strlen(needle);
271 
272  /* return haystack if needle is empty */
273  if (needle_length == 0)
274  return (char *)(intptr_t)(haystack);
275 
276  haystack_length = strlen(haystack);
277  while (needle_length <= haystack_length) {
278  if (XLALStringNCaseCompare(haystack, needle, needle_length) == 0)
279  return (char *)(intptr_t)(haystack);
280  --haystack_length;
281  ++haystack;
282  }
283 
284  /* needle not found in haystack */
285  return NULL;
286 }
287 
288 /**
289  * Return the next token delimited by any character in 'delim' from the string 's', which is updated
290  * to point just pass the returned token. If 'empty' is true, empty tokens are accepted.
291  */
292 char *XLALStringToken(char **s, const char *delim, int empty)
293 {
294 
295  if (*s == NULL) {
296  return NULL;
297  }
298 
299  /* based on implementations of strtok_r() and strsep() in glibc */
300  char *begin = *s;
301  if (!empty) {
302  begin += strspn(begin, delim);
303  if (*begin == '\0') {
304  *s = NULL;
305  return NULL;
306  }
307  }
308  char *end = strpbrk(begin, delim);
309  if (end != NULL) {
310  *end++ = '\0';
311  *s = end;
312  } else {
313  *s = NULL;
314  }
315 
316  return begin;
317 
318 }
319 
320 /**
321  * Return the string 's' applying the function 'f(c, param)' to all characters 'c'.
322  * If 'f()' returns < 0, the character is stripped from the string.
323  */
324 char *XLALStringTranslate(char *s, int (*f)(int, void*), void *param)
325 {
326 
327  if (s == NULL || f == NULL) {
328  return s;
329  }
330 
331  char *p = s;
332  for (char *q = s; *q != '\0'; ++q) {
333  int r = f( ((int) *q ), param );
334  if (r >= 0) {
335  *p = (char) r;
336  ++p;
337  }
338  }
339  *p = '\0';
340 
341  return s;
342 
343 }
344 
345 static int strip_chars(int c, void *param)
346 {
347  int (*f)(int) = (int (*)(int)) param;
348  return f(c) ? -1 : c;
349 }
350 
351 /**
352  * Return the string 's' with all characters for which 'f()' is true removed
353  */
354 char *XLALStringStripChars(char *s, int (*f)(int))
355 {
356  return XLALStringTranslate(s, strip_chars, f);
357 }
358 
359 static int keep_chars(int c, void *param)
360 {
361  int (*f)(int) = (int (*)(int)) param;
362  return f(c) ? c : -1;
363 }
364 
365 /**
366  * Return the string 's' with all characters for which 'f()' is false removed
367  */
368 char *XLALStringKeepChars(char *s, int (*f)(int))
369 {
370  return XLALStringTranslate(s, keep_chars, f);
371 }
372 
373 static int replace(int c, void *param)
374 {
375  int *from_to = ((int*) param);
376  return (c == from_to[0]) ? from_to[1] : c;
377 }
378 
379 /**
380  * Return the string 's' with all characters 'from' replaced with 'to'
381  */
382 char *XLALStringReplaceChar(char *s, const int from, const int to)
383 {
384  int from_to[2] = { from, to };
385  return XLALStringTranslate(s, replace, &from_to);
386 }
static const UINT4 c1
Definition: LALCityHash.c:146
static const UINT4 c2
Definition: LALCityHash.c:147
#define LALRealloc(p, n)
Definition: LALMalloc.h:95
static int keep_chars(int c, void *param)
Definition: LALString.c:359
static int replace(int c, void *param)
Definition: LALString.c:373
static int strip_chars(int c, void *param)
Definition: LALString.c:345
char * XLALStringAppendFmt(char *s, const char *fmt,...)
Append the formatted string 'fmt' to the string 's', which is reallocated with XLALRealloc() to the r...
Definition: LALString.c:69
int XLALStringPrint(char *s, size_t n, const char *fmt,...)
Like snprintf but doesn't print format truncation warnings with GCC.
Definition: LALString.c:28
static const BufferList empty
static double f(double theta, double y, double xi)
Definition: XLALMarcumQ.c:258
uint32_t UINT4
Four-byte unsigned integer.
#define XLALRealloc(p, n)
Definition: LALMalloc.h:46
char * XLALStringStripChars(char *s, int(*f)(int))
Return the string 's' with all characters for which 'f()' is true removed.
Definition: LALString.c:354
int XLALStringToLowerCase(char *string)
Turn a string in-place into lowercase without using locale-dependent functions.
Definition: LALString.c:153
char * XLALStringReplaceChar(char *s, const int from, const int to)
Return the string 's' with all characters 'from' replaced with 'to'.
Definition: LALString.c:382
int XLALStringCaseCompare(const char *s1, const char *s2)
Compare two strings, ignoring case and without using locale-dependent functions.
Definition: LALString.c:210
char * XLALStringTranslate(char *s, int(*f)(int, void *), void *param)
Return the string 's' applying the function 'f(c, param)' to all characters 'c'.
Definition: LALString.c:324
size_t XLALStringCopy(char *dst, const char *src, size_t size)
Copy sources string src to destination string dst.
Definition: LALString.c:104
char * XLALStringDuplicate(const char *s)
Like strdup but uses LAL allocation routines (free with LALFree).
Definition: LALString.c:89
char * XLALStringCaseSubstring(const char *haystack, const char *needle)
Locates substring needle in string haystack, ignoring case and without using locale-dependent functio...
Definition: LALString.c:267
size_t XLALStringConcatenate(char *dst, const char *src, size_t size)
Concatenate sources string src to the end of destination string dst.
Definition: LALString.c:131
char * XLALStringKeepChars(char *s, int(*f)(int))
Return the string 's' with all characters for which 'f()' is false removed.
Definition: LALString.c:368
char * XLALStringAppend(char *s, const char *append)
Like strcat but dynamically reallocates string with LALRealloc.
Definition: LALString.c:50
int XLALStringNCaseCompare(const char *s1, const char *s2, size_t n)
Compare the first N characters of two strings, ignoring case and without using locale-dependent funct...
Definition: LALString.c:219
int XLALStringToUpperCase(char *string)
Turn a string in-place into uppercase without using locale-dependent functions.
Definition: LALString.c:182
char * XLALStringToken(char **s, const char *delim, int empty)
Return the next token delimited by any character in 'delim' from the string 's', which is updated to ...
Definition: LALString.c:292
static const INT4 r
Definition: Random.c:82
static const INT4 m
Definition: Random.c:80
static const INT4 q
Definition: Random.c:81
#define XLAL_ERROR_NULL(...)
Macro to invoke a failure from a XLAL routine returning a pointer.
Definition: XLALError.h:713
#define XLAL_CHECK(assertion,...)
Macro to test an assertion and invoke a failure if it is not true in a function that returns an integ...
Definition: XLALError.h:810
#define XLAL_CHECK_NULL(assertion,...)
Macro to test an assertion and invoke a failure if it is not true in a function that returns a pointe...
Definition: XLALError.h:825
@ XLAL_ENOMEM
Memory allocation error.
Definition: XLALError.h:407
@ XLAL_SUCCESS
Success return value (not an error number)
Definition: XLALError.h:401
@ XLAL_EFAULT
Invalid pointer.
Definition: XLALError.h:408
@ XLAL_ESYS
System error.
Definition: XLALError.h:442
@ XLAL_EINVAL
Invalid argument.
Definition: XLALError.h:409