strings.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  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. * If <em>s</em> is NULL then empty string is returned.
  71. *
  72. * \param s string
  73. *
  74. * \return pointer to newly allocated string
  75. */
  76. char *G_store(const char *s)
  77. {
  78. char *buf;
  79. if (s == NULL) {
  80. buf = G_malloc(sizeof(char));
  81. buf[0] = '\0';
  82. }
  83. else {
  84. buf = G_malloc(strlen(s) + 1);
  85. strcpy(buf, s);
  86. }
  87. return buf;
  88. }
  89. /*!
  90. * \brief Replace all occurencies of character in string bug with new
  91. *
  92. * \param[in,out] bug base string
  93. * \param[in] character character to replace
  94. * \param[in] new new character
  95. *
  96. * \return bug string
  97. */
  98. char *G_strchg(char *bug, char character, char new)
  99. {
  100. char *help = bug;
  101. while (*help) {
  102. if (*help == character)
  103. *help = new;
  104. help++;
  105. }
  106. return bug;
  107. }
  108. /*!
  109. * \brief Replace all occurencies of old_str in buffer with new_str
  110. *
  111. * Code example:
  112. * \code
  113. * char *name;
  114. * name = G_str_replace ( inbuf, ".exe", "" );
  115. * ...
  116. * G_free (name);
  117. * \endcode
  118. *
  119. * \param buffer input string buffer
  120. * \param old_str string to be replaced
  121. * \param new_str new string
  122. *
  123. * \return the newly allocated string, input buffer is unchanged
  124. */
  125. char *G_str_replace(const char *buffer, const char *old_str, const char *new_str)
  126. {
  127. char *B, *R;
  128. const char *N;
  129. char *replace;
  130. int count, len;
  131. /* Make sure old_str and new_str are not NULL */
  132. if (old_str == NULL || new_str == NULL)
  133. return G_store(buffer);
  134. /* Make sure buffer is not NULL */
  135. if (buffer == NULL)
  136. return NULL;
  137. /* Make sure old_str occurs */
  138. B = strstr(buffer, old_str);
  139. if (B == NULL)
  140. /* return NULL; */
  141. return G_store(buffer);
  142. if (strlen(new_str) > strlen(old_str)) {
  143. /* Count occurences of old_str */
  144. count = 0;
  145. len = strlen(old_str);
  146. B = buffer;
  147. while (B != NULL && *B != '\0') {
  148. B = strstr(B, old_str);
  149. if (B != NULL) {
  150. B += len;
  151. count++;
  152. }
  153. }
  154. len = count * (strlen(new_str) - strlen(old_str))
  155. + strlen(buffer);
  156. }
  157. else
  158. len = strlen(buffer);
  159. /* Allocate new replacement */
  160. replace = G_malloc(len + 1);
  161. if (replace == NULL)
  162. return NULL;
  163. /* Replace old_str with new_str */
  164. B = buffer;
  165. R = replace;
  166. len = strlen(old_str);
  167. while (*B != '\0') {
  168. if (*B == old_str[0] && strncmp(B, old_str, len) == 0) {
  169. N = new_str;
  170. while (*N != '\0')
  171. *R++ = *N++;
  172. B += len;
  173. }
  174. else {
  175. *R++ = *B++;
  176. }
  177. }
  178. *R = '\0';
  179. return replace;
  180. }
  181. /*!
  182. * \brief Removes all leading and trailing white space from string.
  183. *
  184. * \param[in,out] buf buffer to be worked on
  185. *
  186. * \return
  187. */
  188. void G_strip(char *buf)
  189. {
  190. char *a, *b;
  191. /* remove leading white space */
  192. for (a = b = buf; *a == ' ' || *a == '\t'; a++) ;
  193. if (a != b)
  194. while ((*b++ = *a++)) ;
  195. /* remove trailing white space */
  196. for (a = buf; *a; a++) ;
  197. if (a != buf) {
  198. for (a--; *a == ' ' || *a == '\t'; a--) ;
  199. a++;
  200. *a = 0;
  201. }
  202. }
  203. /*!
  204. * \brief Chop leading and trailing white spaces:
  205. * \verbatim space, \f, \n, \r, \t, \v \endverbatim
  206. *
  207. * modified copy of G_squeeze(); RB March 2000 <Radim.Blazek@dhv.cz>
  208. *
  209. * \param line buffer to be worked on
  210. *
  211. * \return pointer to string
  212. */
  213. char *G_chop(char *line)
  214. {
  215. char *f = line, *t = line;
  216. while (isspace(*f)) /* go to first non white-space char */
  217. f++;
  218. if (!*f) { /* no more chars in string */
  219. *t = '\0';
  220. return (line);
  221. }
  222. for (t = line; *t; t++) /* go to end */
  223. ;
  224. while (isspace(*--t)) ;
  225. *++t = '\0'; /* remove trailing white-spaces */
  226. t = line;
  227. while (*f) /* copy */
  228. *t++ = *f++;
  229. *t = '\0';
  230. return (line);
  231. }
  232. /*!
  233. * \brief Convert string to upper case
  234. *
  235. * \param[in,out] str pointer to string
  236. */
  237. void G_str_to_upper(char *str)
  238. {
  239. int i = 0;
  240. if (!str)
  241. return;
  242. while (str[i]) {
  243. str[i] = toupper(str[i]);
  244. i++;
  245. }
  246. }
  247. /*!
  248. * \brief Convert string to lower case
  249. *
  250. * \param[in,out] str pointer to string
  251. */
  252. void G_str_to_lower(char *str)
  253. {
  254. int i = 0;
  255. if (!str)
  256. return;
  257. while (str[i]) {
  258. str[i] = tolower(str[i]);
  259. i++;
  260. }
  261. }
  262. /*!
  263. * \brief Make string SQL compliant
  264. *
  265. * \param[in,out] str pointer to string
  266. *
  267. * \return number of changed characters
  268. */
  269. int G_str_to_sql(char *str)
  270. {
  271. int count;
  272. char *c;
  273. count = 0;
  274. if (!str || !*str)
  275. return 0;
  276. c = str;
  277. while (*c) {
  278. *c = toascii(*c);
  279. if (!(*c >= 'A' && *c <= 'Z') && !(*c >= 'a' && *c <= 'z') &&
  280. !(*c >= '0' && *c <= '9')) {
  281. *c = '_';
  282. count++;
  283. }
  284. c++;
  285. }
  286. c = str;
  287. if (!(*c >= 'A' && *c <= 'Z') && !(*c >= 'a' && *c <= 'z')) {
  288. *c = 'x';
  289. count++;
  290. }
  291. return count;
  292. }
  293. /*!
  294. * \brief Remove superfluous white space.
  295. *
  296. * Leading and trailing white space is removed from the string
  297. * <b>line</b> and internal white space which is more than one character
  298. * is reduced to a single space character. White space here means
  299. * spaces, tabs, linefeeds, newlines, and formfeeds.
  300. *
  301. * \param[in,out] line
  302. * \return Pointer to <b>line</b>
  303. */
  304. char *G_squeeze(char *line)
  305. {
  306. char *f = line, *t = line;
  307. int l;
  308. /* skip over space at the beginning of the line. */
  309. while (isspace(*f))
  310. f++;
  311. while (*f)
  312. if (!isspace(*f))
  313. *t++ = *f++;
  314. else if (*++f)
  315. if (!isspace(*f))
  316. *t++ = ' ';
  317. *t = '\0';
  318. l = strlen(line) - 1;
  319. if (*(line + l) == '\n')
  320. *(line + l) = '\0';
  321. return line;
  322. }