strings.c 8.3 KB

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