strings.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /*!
  2. * \file 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 by the GRASS Development Team
  9. *
  10. * This program is free software under the GNU General Public
  11. * License (>=v2). Read the file COPYING that comes with GRASS
  12. * for details.
  13. *
  14. * \author Dave Gerdes (USACERL), Michael Shapiro (USACERL), Amit
  15. * Parghi (USACERL), Bernhard Reiter (Intevation GmbH, Germany) and
  16. * many others
  17. */
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include <ctype.h>
  21. #include <sys/types.h>
  22. #include <grass/gis.h>
  23. #ifndef NULL
  24. #define NULL 0
  25. #endif
  26. /*!
  27. * \brief String compare ignoring case (upper or lower)
  28. *
  29. * Returning a value that has the same sign as the difference between
  30. * the first differing pair of characters
  31. *
  32. * \param[in] x first string to compare
  33. * \param[in] y second string to compare
  34. *
  35. * \return 0 the two strings are equal
  36. * \return -1, 1
  37. */
  38. int G_strcasecmp(const char *x, const char *y)
  39. {
  40. int xx, yy;
  41. if (!x)
  42. return y ? -1 : 0;
  43. if (!y)
  44. return x ? 1 : 0;
  45. while (*x && *y) {
  46. xx = *x++;
  47. yy = *y++;
  48. if (xx >= 'A' && xx <= 'Z')
  49. xx = xx + 'a' - 'A';
  50. if (yy >= 'A' && yy <= 'Z')
  51. yy = yy + 'a' - 'A';
  52. if (xx < yy)
  53. return -1;
  54. if (xx > yy)
  55. return 1;
  56. }
  57. if (*x)
  58. return 1;
  59. if (*y)
  60. return -1;
  61. return 0;
  62. }
  63. /*!
  64. * \brief Copy string to allocated memory.
  65. *
  66. * This routine allocates enough memory to hold the string <b>s</b>,
  67. * copies <b>s</b> to the allocated memory, and returns a pointer
  68. * to the allocated memory.
  69. *
  70. * \param[in] s string
  71. * \return pointer to newly allocated string
  72. */
  73. char *G_store(const char *s)
  74. {
  75. char *buf;
  76. buf = G_malloc(strlen(s) + 1);
  77. strcpy(buf, s);
  78. return buf;
  79. }
  80. /*!
  81. * \brief Replace all occurencies of character in string bug with new
  82. *
  83. * \param[in,out] bug base string
  84. * \param[in] character character to replace
  85. * \param[in] new new character
  86. *
  87. * \return bug string
  88. */
  89. char *G_strchg(char *bug, char character, char new)
  90. {
  91. char *help = bug;
  92. while (*help) {
  93. if (*help == character)
  94. *help = new;
  95. help++;
  96. }
  97. return bug;
  98. }
  99. /*!
  100. * \brief Replace all occurencies of old_str in buffer with new_str
  101. *
  102. * Code example:
  103. * \code
  104. * char *name;
  105. * name = G_str_replace ( inbuf, ".exe", "" );
  106. * ...
  107. * G_free (name);
  108. * \endcode
  109. *
  110. * \param[in,out] buffer main string
  111. * \param[in] old_str string to replace
  112. * \param[in] new_str new string
  113. *
  114. * \return the newly allocated string, input buffer is unchanged
  115. */
  116. char *G_str_replace(char *buffer, const char *old_str, const char *new_str)
  117. {
  118. char *B, *R;
  119. const char *N;
  120. char *replace;
  121. int count, len;
  122. /* Make sure old_str and new_str are not NULL */
  123. if (old_str == NULL || new_str == NULL)
  124. return G_store(buffer);
  125. /* Make sure buffer is not NULL */
  126. if (buffer == NULL)
  127. return NULL;
  128. /* Make sure old_str occurs */
  129. B = strstr(buffer, old_str);
  130. if (B == NULL)
  131. /* return NULL; */
  132. return G_store(buffer);
  133. if (strlen(new_str) > strlen(old_str)) {
  134. /* Count occurences of old_str */
  135. count = 0;
  136. len = strlen(old_str);
  137. B = buffer;
  138. while (B != NULL && *B != '\0') {
  139. B = strstr(B, old_str);
  140. if (B != NULL) {
  141. B += len;
  142. count++;
  143. }
  144. }
  145. len = count * (strlen(new_str) - strlen(old_str))
  146. + strlen(buffer);
  147. }
  148. else
  149. len = strlen(buffer);
  150. /* Allocate new replacement */
  151. replace = G_malloc(len + 1);
  152. if (replace == NULL)
  153. return NULL;
  154. /* Replace old_str with new_str */
  155. B = buffer;
  156. R = replace;
  157. len = strlen(old_str);
  158. while (*B != '\0') {
  159. if (*B == old_str[0] && strncmp(B, old_str, len) == 0) {
  160. N = new_str;
  161. while (*N != '\0')
  162. *R++ = *N++;
  163. B += len;
  164. }
  165. else {
  166. *R++ = *B++;
  167. }
  168. }
  169. *R = '\0';
  170. return replace;
  171. }
  172. /*!
  173. * \brief Removes all leading and trailing white space from string.
  174. *
  175. * \param[in,out] buf buffer to be worked on
  176. *
  177. * \return
  178. */
  179. void G_strip(char *buf)
  180. {
  181. char *a, *b;
  182. /* remove leading white space */
  183. for (a = b = buf; *a == ' ' || *a == '\t'; a++) ;
  184. if (a != b)
  185. while ((*b++ = *a++)) ;
  186. /* remove trailing white space */
  187. for (a = buf; *a; a++) ;
  188. if (a != buf) {
  189. for (a--; *a == ' ' || *a == '\t'; a--) ;
  190. a++;
  191. *a = 0;
  192. }
  193. }
  194. /*!
  195. * \brief Chop leading and trailing white spaces:
  196. * \verbatim space, \f, \n, \r, \t, \v \endverbatim
  197. *
  198. * modified copy of G_squeeze(); RB March 2000 <Radim.Blazek@dhv.cz>
  199. *
  200. * \param line buffer to be worked on
  201. *
  202. * \return pointer to string
  203. */
  204. char *G_chop(char *line)
  205. {
  206. char *f = line, *t = line;
  207. while (isspace(*f)) /* go to first non white-space char */
  208. f++;
  209. if (!*f) { /* no more chars in string */
  210. *t = '\0';
  211. return (line);
  212. }
  213. for (t = line; *t; t++) /* go to end */
  214. ;
  215. while (isspace(*--t)) ;
  216. *++t = '\0'; /* remove trailing white-spaces */
  217. t = line;
  218. while (*f) /* copy */
  219. *t++ = *f++;
  220. *t = '\0';
  221. return (line);
  222. }
  223. /*!
  224. * \brief Convert string to upper case
  225. *
  226. * \param[in,out] str pointer to string
  227. */
  228. void G_str_to_upper(char *str)
  229. {
  230. int i = 0;
  231. if (!str)
  232. return;
  233. while (str[i]) {
  234. str[i] = toupper(str[i]);
  235. i++;
  236. }
  237. }
  238. /*!
  239. * \brief Convert string to lower case
  240. *
  241. * \param[in,out] str pointer to string
  242. */
  243. void G_str_to_lower(char *str)
  244. {
  245. int i = 0;
  246. if (!str)
  247. return;
  248. while (str[i]) {
  249. str[i] = tolower(str[i]);
  250. i++;
  251. }
  252. }
  253. /*!
  254. * \brief Make string SQL compliant
  255. *
  256. * \param[in,out] str pointer to string
  257. *
  258. * \return number of changed characters
  259. */
  260. int G_str_to_sql(char *str)
  261. {
  262. int count;
  263. char *c;
  264. count = 0;
  265. if (!str || !*str)
  266. return 0;
  267. c = str;
  268. while (*c) {
  269. *c = toascii(*c);
  270. if (!(*c >= 'A' && *c <= 'Z') && !(*c >= 'a' && *c <= 'z') &&
  271. !(*c >= '0' && *c <= '9')) {
  272. *c = '_';
  273. count++;
  274. }
  275. c++;
  276. }
  277. c = str;
  278. if (!(*c >= 'A' && *c <= 'Z') && !(*c >= 'a' && *c <= 'z')) {
  279. *c = 'x';
  280. count++;
  281. }
  282. return count;
  283. }
  284. /*!
  285. * \brief Remove superfluous white space.
  286. *
  287. * Leading and trailing white space is removed from the string
  288. * <b>line</b> and internal white space which is more than one character
  289. * is reduced to a single space character. White space here means
  290. * spaces, tabs, linefeeds, newlines, and formfeeds.
  291. *
  292. * \param[in,out] line
  293. * \return Pointer to <b>line</b>
  294. */
  295. char *G_squeeze(char *line)
  296. {
  297. char *f = line, *t = line;
  298. int l;
  299. /* skip over space at the beginning of the line. */
  300. while (isspace(*f))
  301. f++;
  302. while (*f)
  303. if (!isspace(*f))
  304. *t++ = *f++;
  305. else if (*++f)
  306. if (!isspace(*f))
  307. *t++ = ' ';
  308. *t = '\0';
  309. l = strlen(line) - 1;
  310. if (*(line + l) == '\n')
  311. *(line + l) = '\0';
  312. return line;
  313. }