strings.c 7.1 KB

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