LAL 7.7.0.1-678514e
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. */
28int 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. */
50char *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 */
69char *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). */
89char *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 */
104size_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 */
131size_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 */
153int 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 */
182int 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 */
210int 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 */
219int 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 */
267char * 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 */
292char *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 */
324char *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
345static 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 */
354char *XLALStringStripChars(char *s, int (*f)(int))
355{
357}
358
359static 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 */
368char *XLALStringKeepChars(char *s, int (*f)(int))
369{
370 return XLALStringTranslate(s, keep_chars, f);
371}
372
373static 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 */
382char *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
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
static int strip_chars(int c, void *param)
Definition: LALString.c:345
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
int XLALStringToLowerCase(char *string)
Turn a string in-place into lowercase without using locale-dependent functions.
Definition: LALString.c:153
char * XLALStringStripChars(char *s, int(*f)(int))
Return the string 's' with all characters for which 'f()' is true removed.
Definition: LALString.c:354
char * XLALStringDuplicate(const char *s)
Like strdup but uses LAL allocation routines (free with LALFree).
Definition: LALString.c:89
int XLALStringCaseCompare(const char *s1, const char *s2)
Compare two strings, ignoring case and without using locale-dependent functions.
Definition: LALString.c:210
size_t XLALStringCopy(char *dst, const char *src, size_t size)
Copy sources string src to destination string dst.
Definition: LALString.c:104
char * XLALStringAppend(char *s, const char *append)
Like strcat but dynamically reallocates string with LALRealloc.
Definition: LALString.c:50
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
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
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
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
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
int XLALStringToUpperCase(char *string)
Turn a string in-place into uppercase without using locale-dependent functions.
Definition: LALString.c:182
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
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