strings.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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 Copy string to allocated memory and convert copied string
  78. to upper case
  79. This routine allocates enough memory to hold the string <b>s</b>,
  80. copies <em>s</em> to the allocated memory, and returns a pointer
  81. to the allocated memory.
  82. If <em>s</em> is NULL then empty string is returned.
  83. \param s string
  84. \return pointer to newly allocated upper case string
  85. */
  86. char *G_store_upper(const char *s)
  87. {
  88. char *u_s;
  89. u_s = G_store(s);
  90. G_str_to_upper(u_s);
  91. return u_s;
  92. }
  93. /*!
  94. \brief Copy string to allocated memory and convert copied string
  95. to lower case
  96. This routine allocates enough memory to hold the string <b>s</b>,
  97. copies <em>s</em> to the allocated memory, and returns a pointer
  98. to the allocated memory.
  99. If <em>s</em> is NULL then empty string is returned.
  100. \param s string
  101. \return pointer to newly allocated lower case string
  102. */
  103. char *G_store_lower(const char *s)
  104. {
  105. char *l_s;
  106. l_s = G_store(s);
  107. G_str_to_lower(l_s);
  108. return l_s;
  109. }
  110. /*!
  111. \brief Replace all occurrences of character in string bug with new
  112. \param[in,out] bug base string
  113. \param character character to replace
  114. \param new new character
  115. \return bug string
  116. */
  117. char *G_strchg(char *bug, char character, char new)
  118. {
  119. char *help = bug;
  120. while (*help) {
  121. if (*help == character)
  122. *help = new;
  123. help++;
  124. }
  125. return bug;
  126. }
  127. /*!
  128. \brief Replace all occurrences of old_str in buffer with new_str
  129. Code example:
  130. \code
  131. char *name;
  132. name = G_str_replace ( inbuf, ".exe", "" );
  133. ...
  134. G_free (name);
  135. \endcode
  136. \param buffer input string buffer
  137. \param old_str string to be replaced
  138. \param new_str new string
  139. \return the newly allocated string, input buffer is unchanged
  140. */
  141. char *G_str_replace(const char *buffer, const char *old_str, const char *new_str)
  142. {
  143. char *R;
  144. const char *N, *B;
  145. char *replace;
  146. int count, len;
  147. /* Make sure old_str and new_str are not NULL */
  148. if (old_str == NULL || new_str == NULL)
  149. return G_store(buffer);
  150. /* Make sure buffer is not NULL */
  151. if (buffer == NULL)
  152. return NULL;
  153. /* Make sure old_str occurs */
  154. B = strstr(buffer, old_str);
  155. if (B == NULL)
  156. /* return NULL; */
  157. return G_store(buffer);
  158. if (strlen(new_str) > strlen(old_str)) {
  159. /* Count occurrences of old_str */
  160. count = 0;
  161. len = strlen(old_str);
  162. B = buffer;
  163. while (B != NULL && *B != '\0') {
  164. B = strstr(B, old_str);
  165. if (B != NULL) {
  166. B += len;
  167. count++;
  168. }
  169. }
  170. len = count * (strlen(new_str) - strlen(old_str))
  171. + strlen(buffer);
  172. }
  173. else
  174. len = strlen(buffer);
  175. /* Allocate new replacement */
  176. replace = G_malloc(len + 1);
  177. if (replace == NULL)
  178. return NULL;
  179. /* Replace old_str with new_str */
  180. B = buffer;
  181. R = replace;
  182. len = strlen(old_str);
  183. while (*B != '\0') {
  184. if (*B == old_str[0] && strncmp(B, old_str, len) == 0) {
  185. N = new_str;
  186. while (*N != '\0')
  187. *R++ = *N++;
  188. B += len;
  189. }
  190. else {
  191. *R++ = *B++;
  192. }
  193. }
  194. *R = '\0';
  195. return replace;
  196. }
  197. /*!
  198. \brief Removes all leading and trailing white space from string.
  199. \param[in,out] buf buffer to be worked on
  200. */
  201. void G_strip(char *buf)
  202. {
  203. char *a, *b;
  204. /* remove leading white space */
  205. for (a = b = buf; *a == ' ' || *a == '\t'; a++) ;
  206. if (a != b)
  207. while ((*b++ = *a++)) ;
  208. /* remove trailing white space */
  209. for (a = buf; *a; a++) ;
  210. if (a != buf) {
  211. for (a--; *a == ' ' || *a == '\t'; a--) ;
  212. a++;
  213. *a = 0;
  214. }
  215. }
  216. /*!
  217. \brief Chop leading and trailing white spaces.
  218. \verbatim space, \f, \n, \r, \t, \v \endverbatim
  219. Modified copy of G_squeeze() by RB in March 2000.
  220. \param line buffer to be worked on
  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 = f; *t; t++) /* go from first non white-space char to end */
  233. ;
  234. while (isspace(*--t)) ;
  235. *++t = '\0'; /* remove trailing white-spaces */
  236. if (f != line) {
  237. t = line;
  238. while (*f) /* leading white spaces, shift */
  239. *t++ = *f++;
  240. *t = '\0';
  241. }
  242. return (line);
  243. }
  244. /*!
  245. \brief Convert string to upper case
  246. \param[in,out] str pointer to string
  247. */
  248. void G_str_to_upper(char *str)
  249. {
  250. int i = 0;
  251. if (!str)
  252. return;
  253. while (str[i]) {
  254. str[i] = toupper(str[i]);
  255. i++;
  256. }
  257. }
  258. /*!
  259. \brief Convert string to lower case
  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. \param[in,out] str pointer to string
  275. \return number of changed characters
  276. */
  277. int G_str_to_sql(char *str)
  278. {
  279. int count;
  280. char *c;
  281. count = 0;
  282. if (!str || !*str)
  283. return 0;
  284. c = str;
  285. while (*c) {
  286. *c = toascii(*c);
  287. if (!(*c >= 'A' && *c <= 'Z') && !(*c >= 'a' && *c <= 'z') &&
  288. !(*c >= '0' && *c <= '9')) {
  289. *c = '_';
  290. count++;
  291. }
  292. c++;
  293. }
  294. c = str;
  295. if (!(*c >= 'A' && *c <= 'Z') && !(*c >= 'a' && *c <= 'z')) {
  296. *c = 'x';
  297. count++;
  298. }
  299. return count;
  300. }
  301. /*!
  302. \brief Remove superfluous white space.
  303. Leading and trailing white space is removed from the string
  304. <b>line</b> and internal white space which is more than one character
  305. is reduced to a single space character. White space here means
  306. spaces, tabs, linefeeds, newlines, and formfeeds.
  307. \param[in,out] line
  308. \return Pointer to <b>line</b>
  309. */
  310. void G_squeeze(char *line)
  311. {
  312. char *f = line, *t = line;
  313. int l;
  314. /* skip over space at the beginning of the line. */
  315. while (isspace(*f))
  316. f++;
  317. while (*f)
  318. if (!isspace(*f))
  319. *t++ = *f++;
  320. else if (*++f)
  321. if (!isspace(*f))
  322. *t++ = ' ';
  323. *t = '\0';
  324. l = strlen(line) - 1;
  325. if (*(line + l) == '\n')
  326. *(line + l) = '\0';
  327. }
  328. /*!
  329. \brief Finds the first occurrence of the sub-string in the
  330. null-terminated string ignoring case (upper or lower)
  331. \param str string where to find sub-string
  332. \param substr sub-string
  333. \return a pointer to the first occurrence of sub-string
  334. \return NULL if no occurrences are found
  335. */
  336. char *G_strcasestr(const char *str, const char *substr)
  337. {
  338. const char *p;
  339. const char *q;
  340. int length;
  341. p = substr;
  342. q = str;
  343. length = strlen(substr);
  344. do {
  345. /* match 1st substr char */
  346. while (*q != '\0' && toupper(*q) != toupper(*p)) {
  347. q++;
  348. }
  349. } while (*q != '\0' && G_strncasecmp(p, q, length) != 0 && q++);
  350. if (*q == '\0') {
  351. /* ran off end of str */
  352. return NULL;
  353. }
  354. return (char *) q;
  355. }
  356. int _strncasecmp(const char *x, const char *y, int n)
  357. {
  358. int xx, yy, i;
  359. if (!x)
  360. return y ? -1 : 0;
  361. if (!y)
  362. return x ? 1 : 0;
  363. i = 1;
  364. while (*x && *y) {
  365. xx = *x++;
  366. yy = *y++;
  367. if (xx >= 'A' && xx <= 'Z')
  368. xx = xx + 'a' - 'A';
  369. if (yy >= 'A' && yy <= 'Z')
  370. yy = yy + 'a' - 'A';
  371. if (xx < yy)
  372. return -1;
  373. if (xx > yy)
  374. return 1;
  375. if (n > -1 && i >= n)
  376. return 0;
  377. i++;
  378. }
  379. if (*x)
  380. return 1;
  381. if (*y)
  382. return -1;
  383. return 0;
  384. }