GRASS 8 Programmer's Manual 8.6.0dev(2026)-1878fdfec5
Loading...
Searching...
No Matches
strings.c
Go to the documentation of this file.
1/*!
2 \file lib/gis/strings.c
3
4 \brief GIS Library - string/chring movement functions
5
6 \todo merge interesting functions from ../datetime/scan.c here
7
8 SPDX-FileCopyrightText: 1999-2008, 2011 GRASS Development Team
9 SPDX-License-Identifier: GPL-2.0-or-later
10
11 \author Dave Gerdes (USACERL)
12 \author Michael Shapiro (USACERL)
13 \author Amit Parghi (USACERL)
14 \author Bernhard Reiter (Intevation GmbH, Germany) and many others
15 */
16
17#include <string.h>
18#include <stdlib.h>
19#include <ctype.h>
20#include <sys/types.h>
21#include <grass/gis.h>
22
23#ifndef NULL
24#define NULL 0
25#endif
26
27static void *G__memccpy(void *, const void *, int, size_t);
28static int _strncasecmp(const char *, const char *, int);
29
30/*!
31 \brief String compare ignoring case (upper or lower)
32
33 Returning a value that has the same sign as the difference between
34 the first differing pair of characters.
35
36 Note: strcasecmp() is affected by the locale (LC_CTYPE), while
37 G_strcasecmp() isn't.
38
39 \param x first string to compare
40 \param y second string to compare
41
42 \return 0 the two strings are equal
43 \return -1, 1
44 */
45int G_strcasecmp(const char *x, const char *y)
46{
47 return _strncasecmp(x, y, -1);
48}
49
50/*!
51 \brief String compare ignoring case (upper or lower) - limited
52 number of characters
53
54 Returning a value that has the same sign as the difference between
55 the first differing pair of characters.
56
57 Note: strcasecmp() is affected by the locale (LC_CTYPE), while
58 G_strcasecmp() isn't.
59
60 \param x first string to compare
61 \param y second string to compare
62 \param n number or characters to compare
63
64 \return 0 the two strings are equal
65 \return -1, 1
66 */
67int G_strncasecmp(const char *x, const char *y, int n)
68{
69 return _strncasecmp(x, y, n);
70}
71
72/*!
73 \brief Copy string to allocated memory.
74
75 This routine allocates enough memory to hold the string <b>s</b>,
76 copies <em>s</em> to the allocated memory, and returns a pointer
77 to the allocated memory.
78
79 If <em>s</em> is NULL then empty string is returned.
80
81 \param s string
82
83 \return pointer to newly allocated string
84 */
85char *G_store(const char *s)
86{
87 char *buf;
88
89 if (s == NULL) {
90 buf = G_malloc(sizeof(char));
91 buf[0] = '\0';
92 }
93 else {
94 buf = G_malloc(strlen(s) + 1);
95 strcpy(buf, s);
96 }
97
98 return buf;
99}
100
101/*!
102 \brief Copy string to allocated memory and convert copied string
103 to upper case
104
105 This routine allocates enough memory to hold the string <b>s</b>,
106 copies <em>s</em> to the allocated memory, and returns a pointer
107 to the allocated memory.
108
109 If <em>s</em> is NULL then empty string is returned.
110
111 \param s string
112
113 \return pointer to newly allocated upper case string
114 */
115char *G_store_upper(const char *s)
116{
117 char *u_s;
118
119 u_s = G_store(s);
120 G_str_to_upper(u_s);
121
122 return u_s;
123}
124
125/*!
126 \brief Copy string to allocated memory and convert copied string
127 to lower case
128
129 This routine allocates enough memory to hold the string <b>s</b>,
130 copies <em>s</em> to the allocated memory, and returns a pointer
131 to the allocated memory.
132
133 If <em>s</em> is NULL then empty string is returned.
134
135 \param s string
136
137 \return pointer to newly allocated lower case string
138 */
139char *G_store_lower(const char *s)
140{
141 char *l_s;
142
143 l_s = G_store(s);
145
146 return l_s;
147}
148
149/*!
150 \brief Replace all occurrences of character in string bug with new
151
152 \param[in,out] bug base string
153 \param character character to replace
154 \param new new character
155
156 \return bug string
157 */
158char *G_strchg(char *bug, char character, char new)
159{
160 char *help = bug;
161
162 while (*help) {
163 if (*help == character)
164 *help = new;
165 help++;
166 }
167 return bug;
168}
169
170/*!
171 \brief Replace all occurrences of old_str in buffer with new_str
172
173 Code example:
174 \code
175 char *name;
176 name = G_str_replace ( inbuf, ".exe", "" );
177 ...
178 G_free (name);
179 \endcode
180
181 \param buffer input string buffer
182 \param old_str string to be replaced
183 \param new_str new string
184
185 \return the newly allocated string, input buffer is unchanged
186 */
187char *G_str_replace(const char *buffer, const char *old_str,
188 const char *new_str)
189{
190 char *R;
191 const char *N, *B;
192 char *replace;
193 int count, len;
194
195 /* Make sure old_str and new_str are not NULL */
196 if (old_str == NULL || new_str == NULL)
197 return G_store(buffer);
198 /* Make sure buffer is not NULL */
199 if (buffer == NULL)
200 return NULL;
201
202 /* Make sure old_str occurs */
203 B = strstr(buffer, old_str);
204 if (B == NULL)
205 /* return NULL; */
206 return G_store(buffer);
207
208 if (strlen(new_str) > strlen(old_str)) {
209 /* Count occurrences of old_str */
210 count = 0;
211 len = strlen(old_str);
212 B = buffer;
213 while (B != NULL && *B != '\0') {
214 B = strstr(B, old_str);
215 if (B != NULL) {
216 B += len;
217 count++;
218 }
219 }
220
221 len = count * (strlen(new_str) - strlen(old_str)) + strlen(buffer);
222 }
223 else
224 len = strlen(buffer);
225
226 /* Allocate new replacement */
227 replace = G_malloc(len + 1);
228 if (replace == NULL)
229 return NULL;
230
231 /* Replace old_str with new_str */
232 B = buffer;
233 R = replace;
234 len = strlen(old_str);
235 while (*B != '\0') {
236 if (*B == old_str[0] && strncmp(B, old_str, len) == 0) {
237 N = new_str;
238 while (*N != '\0')
239 *R++ = *N++;
240 B += len;
241 }
242 else {
243 *R++ = *B++;
244 }
245 }
246 *R = '\0';
247
248 return replace;
249}
250
251/*!
252 \brief String concatenation
253
254 Concatenates the strings in src_strings, which consists of num_strings number
255 of strings, with the separator sep. The size of the concatenated string is
256 limited by maxsize.
257
258 \param src_strings array of strings to concatenate
259 \param num_strings count of strings in src_strings
260 \param sep separator string
261 \param maxsize maximum number of characters of returned string
262
263 \return the concatenated string (allocated)
264 */
265char *G_str_concat(const char **src_strings, int num_strings, const char *sep,
266 int maxsize)
267{
268 if (maxsize < 1 || num_strings < 1)
269 return NULL;
270
271 char *concat_str = NULL;
272 char *p = NULL;
273 char *buffer = G_malloc(maxsize * sizeof(char));
274 char *end = buffer + maxsize;
275
276 memset(buffer, 0, maxsize);
277 for (int i = 0; i < num_strings; i++) {
278 if (i == 0)
279 p = (char *)G__memccpy(buffer, src_strings[i], '\0', maxsize);
280 else {
281 if (p)
282 p = (char *)G__memccpy(p - 1, sep, '\0', end - p);
283 if (p)
284 p = (char *)G__memccpy(p - 1, src_strings[i], '\0', end - p);
285 }
286 }
287 concat_str = G_store(buffer);
288 G_free(buffer);
289
290 return concat_str;
291}
292
293/*!
294 \brief Removes all leading and trailing white space from string.
295
296 \param[in,out] buf buffer to be worked on
297 */
298void G_strip(char *buf)
299{
300 char *a, *b;
301
302 /* remove leading white space */
303 for (a = b = buf; *a == ' ' || *a == '\t'; a++)
304 ;
305 if (a != b)
306 while ((*b++ = *a++))
307 ;
308 /* remove trailing white space */
309 for (a = buf; *a; a++)
310 ;
311 if (a != buf) {
312 for (a--; *a == ' ' || *a == '\t'; a--)
313 ;
314 a++;
315 *a = 0;
316 }
317}
318
319/*!
320 \brief Chop leading and trailing white spaces.
321
322 \verbatim space, \f, \n, \r, \t, \v \endverbatim
323
324 Modified copy of G_squeeze() by RB in March 2000.
325
326 \param line buffer to be worked on
327
328 \return pointer to string
329 */
330char *G_chop(char *line)
331{
332 char *f = line, *t = line;
333
334 while (isspace(*f)) /* go to first non white-space char */
335 f++;
336
337 if (!*f) { /* no more chars in string */
338 *t = '\0';
339 return (line);
340 }
341
342 for (t = f; *t; t++) /* go from first non white-space char to end */
343 ;
344 while (isspace(*--t))
345 ;
346 *++t = '\0'; /* remove trailing white-spaces */
347
348 if (f != line) {
349 t = line;
350 while (*f) /* leading white spaces, shift */
351 *t++ = *f++;
352 *t = '\0';
353 }
354
355 return (line);
356}
357
358/*!
359 \brief Convert string to upper case
360
361 \param[in,out] str pointer to string
362 */
363void G_str_to_upper(char *str)
364{
365 int i = 0;
366
367 if (!str)
368 return;
369
370 while (str[i]) {
371 str[i] = toupper(str[i]);
372 i++;
373 }
374}
375
376/*!
377 \brief Convert string to lower case
378
379 \param[in,out] str pointer to string
380 */
381void G_str_to_lower(char *str)
382{
383 int i = 0;
384
385 if (!str)
386 return;
387
388 while (str[i]) {
389 str[i] = tolower(str[i]);
390 i++;
391 }
392}
393
394/*!
395 \brief Make string SQL compliant
396
397 \param[in,out] str pointer to string
398
399 \return number of changed characters
400 */
401int G_str_to_sql(char *str)
402{
403 int count;
404 char *c;
405
406 count = 0;
407
408 if (!str || !*str)
409 return 0;
410
411 c = str;
412 while (*c) {
413 *c = toascii(*c);
414
415 if (!(*c >= 'A' && *c <= 'Z') && !(*c >= 'a' && *c <= 'z') &&
416 !(*c >= '0' && *c <= '9')) {
417 *c = '_';
418 count++;
419 }
420 c++;
421 }
422
423 c = str;
424 if (!(*c >= 'A' && *c <= 'Z') && !(*c >= 'a' && *c <= 'z')) {
425 *c = 'x';
426 count++;
427 }
428
429 return count;
430}
431
432/*!
433 \brief Remove superfluous white space.
434
435 Leading and trailing white space is removed from the string
436 <b>line</b> and internal white space which is more than one character
437 is reduced to a single space character. White space here means
438 spaces, tabs, linefeeds, newlines, and formfeeds.
439
440 \param[in,out] line
441
442 \return Pointer to <b>line</b>
443 */
444void G_squeeze(char *line)
445{
446 char *f = line, *t = line;
447 int l;
448
449 /* skip over space at the beginning of the line. */
450 while (isspace(*f))
451 f++;
452
453 while (*f)
454 if (!isspace(*f))
455 *t++ = *f++;
456 else if (*++f)
457 if (!isspace(*f))
458 *t++ = ' ';
459 *t = '\0';
460 l = strlen(line) - 1;
461 if (*(line + l) == '\n')
462 *(line + l) = '\0';
463}
464
465/*!
466 \brief Finds the first occurrence of the sub-string in the
467 null-terminated string ignoring case (upper or lower)
468
469 \param str string where to find sub-string
470 \param substr sub-string
471
472 \return a pointer to the first occurrence of sub-string
473 \return NULL if no occurrences are found
474 */
475char *G_strcasestr(const char *str, const char *substr)
476{
477 const char *p;
478 const char *q;
479 int length;
480
481 p = substr;
482 q = str;
483 length = strlen(substr);
484
485 do {
486 /* match 1st substr char */
487 while (*q != '\0' && toupper(*q) != toupper(*p)) {
488 q++;
489 }
490 } while (*q != '\0' && G_strncasecmp(p, q, length) != 0 && q++);
491
492 if (*q == '\0') {
493 /* ran off end of str */
494 return NULL;
495 }
496
497 return (char *)q;
498}
499
500/*!
501 \brief Copy string until character found
502
503 The bytes from string src are copied to string dst. If the character c (as
504 converted to an unsigned char) occurs in the string src, the copy stops and
505 a pointer to the byte after the copy of c in the string dst is returned.
506 Otherwise, n bytes are copied, and a NULL pointer is returned.
507
508 The source and destination strings should not overlap, as the behavior
509 is undefined.
510
511 \param dst destination
512 \param src source
513 \param c stop character
514 \param n max number of bytes to copy
515
516 \return a pointer to the next character in dest after c
517 \return NULL if c was not found in the first n characters of src
518 */
519static void *G__memccpy(void *dst, const void *src, int c, size_t n)
520{
521 const char *s = src;
522 char *ret;
523
524 for (ret = dst; n; ++ret, ++s, --n) {
525 *ret = *s;
526 if ((unsigned char)*ret == (unsigned char)c)
527 return ret + 1;
528 }
529
530 return NULL;
531}
532
533static int _strncasecmp(const char *x, const char *y, int n)
534{
535 int xx, yy, i;
536
537 if (!x)
538 return y ? -1 : 0;
539 if (!y)
540 return x ? 1 : 0;
541
542 i = 1;
543 while (*x && *y) {
544 xx = *x++;
545 yy = *y++;
546 if (xx >= 'A' && xx <= 'Z')
547 xx = xx + 'a' - 'A';
548 if (yy >= 'A' && yy <= 'Z')
549 yy = yy + 'a' - 'A';
550 if (xx < yy)
551 return -1;
552 if (xx > yy)
553 return 1;
554
555 if (n > -1 && i >= n)
556 return 0;
557
558 i++;
559 }
560
561 if (*x)
562 return 1;
563 if (*y)
564 return -1;
565 return 0;
566}
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
#define G_malloc(n)
Definition defs/gis.h:136
#define N
int count
#define strcpy
Definition parson.c:66
double b
Definition r_raster.c:37
double l
Definition r_raster.c:37
double t
Definition r_raster.c:37
#define NULL
Definition strings.c:24
char * G_store_lower(const char *s)
Copy string to allocated memory and convert copied string to lower case.
Definition strings.c:139
int G_str_to_sql(char *str)
Make string SQL compliant.
Definition strings.c:401
int G_strncasecmp(const char *x, const char *y, int n)
String compare ignoring case (upper or lower) - limited number of characters.
Definition strings.c:67
char * G_str_replace(const char *buffer, const char *old_str, const char *new_str)
Replace all occurrences of old_str in buffer with new_str.
Definition strings.c:187
void G_str_to_upper(char *str)
Convert string to upper case.
Definition strings.c:363
void G_str_to_lower(char *str)
Convert string to lower case.
Definition strings.c:381
char * G_chop(char *line)
Chop leading and trailing white spaces.
Definition strings.c:330
char * G_strchg(char *bug, char character, char new)
Replace all occurrences of character in string bug with new.
Definition strings.c:158
char * G_strcasestr(const char *str, const char *substr)
Finds the first occurrence of the sub-string in the null-terminated string ignoring case (upper or lo...
Definition strings.c:475
int G_strcasecmp(const char *x, const char *y)
String compare ignoring case (upper or lower)
Definition strings.c:45
void G_squeeze(char *line)
Remove superfluous white space.
Definition strings.c:444
char * G_store(const char *s)
Copy string to allocated memory.
Definition strings.c:85
void G_strip(char *buf)
Removes all leading and trailing white space from string.
Definition strings.c:298
char * G_str_concat(const char **src_strings, int num_strings, const char *sep, int maxsize)
String concatenation.
Definition strings.c:265
char * G_store_upper(const char *s)
Copy string to allocated memory and convert copied string to upper case.
Definition strings.c:115
#define x