123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564 |
- /*!
- \file lib/gis/strings.c
-
- \brief GIS Library - string/chring movement functions
-
- \todo merge interesting functions from ../datetime/scan.c here
-
- (C) 1999-2008, 2011 by the GRASS Development Team
-
- This program is free software under the GNU General Public License
- (>=v2). Read the file COPYING that comes with GRASS for details.
-
- \author Dave Gerdes (USACERL)
- \author Michael Shapiro (USACERL)
- \author Amit Parghi (USACERL)
- \author Bernhard Reiter (Intevation GmbH, Germany) and many others
- */
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <grass/gis.h>
- #ifndef NULL
- #define NULL 0
- #endif
- static void *G__memccpy(void *, const void *, int, size_t);
- static int _strncasecmp(const char *, const char *, int);
- /*!
- \brief String compare ignoring case (upper or lower)
-
- Returning a value that has the same sign as the difference between
- the first differing pair of characters.
- Note: strcasecmp() is affected by the locale (LC_CTYPE), while
- G_strcasecmp() isn't.
-
- \param x first string to compare
- \param y second string to compare
-
- \return 0 the two strings are equal
- \return -1, 1
- */
- int G_strcasecmp(const char *x, const char *y)
- {
- return _strncasecmp(x, y, -1);
- }
- /*!
- \brief String compare ignoring case (upper or lower) - limited
- number of characters
-
- Returning a value that has the same sign as the difference between
- the first differing pair of characters.
- Note: strcasecmp() is affected by the locale (LC_CTYPE), while
- G_strcasecmp() isn't.
-
- \param x first string to compare
- \param y second string to compare
- \param n number or characters to compare
-
- \return 0 the two strings are equal
- \return -1, 1
- */
- int G_strncasecmp(const char *x, const char *y, int n)
- {
- return _strncasecmp(x, y, n);
- }
- /*!
- \brief Copy string to allocated memory.
-
- This routine allocates enough memory to hold the string <b>s</b>,
- copies <em>s</em> to the allocated memory, and returns a pointer
- to the allocated memory.
-
- If <em>s</em> is NULL then empty string is returned.
-
- \param s string
-
- \return pointer to newly allocated string
- */
- char *G_store(const char *s)
- {
- char *buf;
- if (s == NULL) {
- buf = G_malloc(sizeof(char));
- buf[0] = '\0';
- }
- else {
- buf = G_malloc(strlen(s) + 1);
- strcpy(buf, s);
- }
-
- return buf;
- }
- /*!
- \brief Copy string to allocated memory and convert copied string
- to upper case
-
- This routine allocates enough memory to hold the string <b>s</b>,
- copies <em>s</em> to the allocated memory, and returns a pointer
- to the allocated memory.
-
- If <em>s</em> is NULL then empty string is returned.
-
- \param s string
-
- \return pointer to newly allocated upper case string
- */
- char *G_store_upper(const char *s)
- {
- char *u_s;
- u_s = G_store(s);
- G_str_to_upper(u_s);
- return u_s;
- }
- /*!
- \brief Copy string to allocated memory and convert copied string
- to lower case
-
- This routine allocates enough memory to hold the string <b>s</b>,
- copies <em>s</em> to the allocated memory, and returns a pointer
- to the allocated memory.
-
- If <em>s</em> is NULL then empty string is returned.
-
- \param s string
-
- \return pointer to newly allocated lower case string
- */
- char *G_store_lower(const char *s)
- {
- char *l_s;
- l_s = G_store(s);
- G_str_to_lower(l_s);
- return l_s;
- }
- /*!
- \brief Replace all occurrences of character in string bug with new
-
- \param[in,out] bug base string
- \param character character to replace
- \param new new character
-
- \return bug string
- */
- char *G_strchg(char *bug, char character, char new)
- {
- char *help = bug;
- while (*help) {
- if (*help == character)
- *help = new;
- help++;
- }
- return bug;
- }
- /*!
- \brief Replace all occurrences of old_str in buffer with new_str
-
- Code example:
- \code
- char *name;
- name = G_str_replace ( inbuf, ".exe", "" );
- ...
- G_free (name);
- \endcode
-
- \param buffer input string buffer
- \param old_str string to be replaced
- \param new_str new string
-
- \return the newly allocated string, input buffer is unchanged
- */
- char *G_str_replace(const char *buffer, const char *old_str, const char *new_str)
- {
- char *R;
- const char *N, *B;
- char *replace;
- int count, len;
- /* Make sure old_str and new_str are not NULL */
- if (old_str == NULL || new_str == NULL)
- return G_store(buffer);
- /* Make sure buffer is not NULL */
- if (buffer == NULL)
- return NULL;
- /* Make sure old_str occurs */
- B = strstr(buffer, old_str);
- if (B == NULL)
- /* return NULL; */
- return G_store(buffer);
- if (strlen(new_str) > strlen(old_str)) {
- /* Count occurrences of old_str */
- count = 0;
- len = strlen(old_str);
- B = buffer;
- while (B != NULL && *B != '\0') {
- B = strstr(B, old_str);
- if (B != NULL) {
- B += len;
- count++;
- }
- }
- len = count * (strlen(new_str) - strlen(old_str))
- + strlen(buffer);
- }
- else
- len = strlen(buffer);
- /* Allocate new replacement */
- replace = G_malloc(len + 1);
- if (replace == NULL)
- return NULL;
- /* Replace old_str with new_str */
- B = buffer;
- R = replace;
- len = strlen(old_str);
- while (*B != '\0') {
- if (*B == old_str[0] && strncmp(B, old_str, len) == 0) {
- N = new_str;
- while (*N != '\0')
- *R++ = *N++;
- B += len;
- }
- else {
- *R++ = *B++;
- }
- }
- *R = '\0';
- return replace;
- }
- /*!
- \brief String concatenation
- Concatenates the strings in src_strings, which consists of num_strings number
- of strings, with the separator sep. The size of the concatenated string is
- limited by maxsize.
- \param src_strings array of strings to concatenate
- \param num_strings count of strings in src_strings
- \param sep separator string
- \param maxsize maximum number of characters of returned string
- \return the concatenated string (allocated)
- */
- char *G_str_concat(const char **src_strings, int num_strings,
- const char *sep, int maxsize)
- {
- char buffer[maxsize];
- int i;
- char *end = buffer + maxsize;
- char *p = NULL;
- if (maxsize < 1 || num_strings < 1)
- return NULL;
- memset(buffer, 0, sizeof(buffer));
- for (i = 0; i < num_strings; i++) {
- if (i == 0)
- p = (char *)G__memccpy(buffer, src_strings[i], '\0', maxsize);
- else {
- if (p)
- p = (char *)G__memccpy(p - 1, sep, '\0', end - p);
- if (p)
- p = (char *)G__memccpy(p - 1, src_strings[i], '\0', end - p);
- }
- }
- return G_store(buffer);
- }
- /*!
- \brief Removes all leading and trailing white space from string.
-
- \param[in,out] buf buffer to be worked on
- */
- void G_strip(char *buf)
- {
- char *a, *b;
- /* remove leading white space */
- for (a = b = buf; *a == ' ' || *a == '\t'; a++) ;
- if (a != b)
- while ((*b++ = *a++)) ;
- /* remove trailing white space */
- for (a = buf; *a; a++) ;
- if (a != buf) {
- for (a--; *a == ' ' || *a == '\t'; a--) ;
- a++;
- *a = 0;
- }
- }
- /*!
- \brief Chop leading and trailing white spaces.
-
- \verbatim space, \f, \n, \r, \t, \v \endverbatim
-
- Modified copy of G_squeeze() by RB in March 2000.
-
- \param line buffer to be worked on
-
- \return pointer to string
- */
- char *G_chop(char *line)
- {
- char *f = line, *t = line;
- while (isspace(*f)) /* go to first non white-space char */
- f++;
- if (!*f) { /* no more chars in string */
- *t = '\0';
- return (line);
- }
- for (t = f; *t; t++) /* go from first non white-space char to end */
- ;
- while (isspace(*--t)) ;
- *++t = '\0'; /* remove trailing white-spaces */
- if (f != line) {
- t = line;
- while (*f) /* leading white spaces, shift */
- *t++ = *f++;
- *t = '\0';
- }
- return (line);
- }
- /*!
- \brief Convert string to upper case
-
- \param[in,out] str pointer to string
- */
- void G_str_to_upper(char *str)
- {
- int i = 0;
- if (!str)
- return;
- while (str[i]) {
- str[i] = toupper(str[i]);
- i++;
- }
- }
- /*!
- \brief Convert string to lower case
-
- \param[in,out] str pointer to string
- */
- void G_str_to_lower(char *str)
- {
- int i = 0;
- if (!str)
- return;
- while (str[i]) {
- str[i] = tolower(str[i]);
- i++;
- }
- }
- /*!
- \brief Make string SQL compliant
-
- \param[in,out] str pointer to string
-
- \return number of changed characters
- */
- int G_str_to_sql(char *str)
- {
- int count;
- char *c;
- count = 0;
- if (!str || !*str)
- return 0;
- c = str;
- while (*c) {
- *c = toascii(*c);
- if (!(*c >= 'A' && *c <= 'Z') && !(*c >= 'a' && *c <= 'z') &&
- !(*c >= '0' && *c <= '9')) {
- *c = '_';
- count++;
- }
- c++;
- }
- c = str;
- if (!(*c >= 'A' && *c <= 'Z') && !(*c >= 'a' && *c <= 'z')) {
- *c = 'x';
- count++;
- }
- return count;
- }
- /*!
- \brief Remove superfluous white space.
-
- Leading and trailing white space is removed from the string
- <b>line</b> and internal white space which is more than one character
- is reduced to a single space character. White space here means
- spaces, tabs, linefeeds, newlines, and formfeeds.
-
- \param[in,out] line
- \return Pointer to <b>line</b>
- */
- void G_squeeze(char *line)
- {
- char *f = line, *t = line;
- int l;
- /* skip over space at the beginning of the line. */
- while (isspace(*f))
- f++;
- while (*f)
- if (!isspace(*f))
- *t++ = *f++;
- else if (*++f)
- if (!isspace(*f))
- *t++ = ' ';
- *t = '\0';
- l = strlen(line) - 1;
- if (*(line + l) == '\n')
- *(line + l) = '\0';
- }
- /*!
- \brief Finds the first occurrence of the sub-string in the
- null-terminated string ignoring case (upper or lower)
-
- \param str string where to find sub-string
- \param substr sub-string
-
- \return a pointer to the first occurrence of sub-string
- \return NULL if no occurrences are found
- */
- char *G_strcasestr(const char *str, const char *substr)
- {
- const char *p;
- const char *q;
- int length;
- p = substr;
- q = str;
- length = strlen(substr);
- do {
- /* match 1st substr char */
- while (*q != '\0' && toupper(*q) != toupper(*p)) {
- q++;
- }
- } while (*q != '\0' && G_strncasecmp(p, q, length) != 0 && q++);
-
- if (*q == '\0') {
- /* ran off end of str */
- return NULL;
- }
-
- return (char *) q;
- }
- /*!
- \brief Copy string until character found
- The bytes from string src are copied to string dst. If the character c (as
- converted to an unsigned char) occurs in the string src, the copy stops and
- a pointer to the byte after the copy of c in the string dst is returned.
- Otherwise, n bytes are copied, and a NULL pointer is returned.
- The source and destination strings should not overlap, as the behavior
- is undefined.
- \param dst destination
- \param src source
- \param c stop character
- \param n max number of bytes to copy
- \return a pointer to the next character in dest after c
- \return NULL if c was not found in the first n characters of src
- */
- static void *G__memccpy(void *dst, const void *src, int c, size_t n)
- {
- const char *s = src;
- char *ret;
- for (ret = dst; n; ++ret, ++s, --n) {
- *ret = *s;
- if ((unsigned char)*ret == (unsigned char)c)
- return ret + 1;
- }
- return NULL;
- }
- static int _strncasecmp(const char *x, const char *y, int n)
- {
- int xx, yy, i;
- if (!x)
- return y ? -1 : 0;
- if (!y)
- return x ? 1 : 0;
- i = 1;
- while (*x && *y) {
- xx = *x++;
- yy = *y++;
- if (xx >= 'A' && xx <= 'Z')
- xx = xx + 'a' - 'A';
- if (yy >= 'A' && yy <= 'Z')
- yy = yy + 'a' - 'A';
- if (xx < yy)
- return -1;
- if (xx > yy)
- return 1;
-
- if (n > -1 && i >= n)
- return 0;
-
- i++;
- }
-
- if (*x)
- return 1;
- if (*y)
- return -1;
- return 0;
- }
|