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