strings.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  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. static char *G_strend(const char *S)
  27. {
  28. while (*S)
  29. S++;
  30. return (char *)S;
  31. }
  32. /*!
  33. * \brief Copies characters from the string F into the string T.
  34. *
  35. * This function has undefined results if the strings overlap.
  36. *
  37. * \param[out] T target string
  38. * \param[in] F source string
  39. *
  40. * \return pointer to T
  41. */
  42. char *G_strcpy(char *T, const char *F)
  43. {
  44. char *d = T;
  45. while ((*d++ = *F++)) ;
  46. return (T);
  47. }
  48. /*!
  49. * \brief Copies characters from the string F into the string T.
  50. *
  51. * Copies just the first n characters from the string F. At the end
  52. * the null terminator is written into the string T.
  53. *
  54. * \param[out] T target string
  55. * \param[in] F source string
  56. * \param[in] n number of characters to copy
  57. *
  58. * \return T value
  59. */
  60. char *G_chrcpy(char *T, const char *F, int n)
  61. {
  62. char *d = T;
  63. while (n--)
  64. *d++ = *F++;
  65. *d = '\0';
  66. return (T);
  67. }
  68. /*!
  69. * \brief This function is similar to G_chrcpy() but always copies at least
  70. * n characters into the string T.
  71. *
  72. * If the length of F is more than n, then copies just the first n
  73. * characters. At the end the null terminator is written into the
  74. * string T.
  75. *
  76. * \param[out] T target string
  77. * \param[in] F source string
  78. * \param[in] n number of characters to copy
  79. *
  80. * \return T value
  81. */
  82. char *G_strncpy(char *T, const char *F, int n)
  83. {
  84. char *d = T;
  85. while (n-- && *F)
  86. *d++ = *F++;
  87. *d = '\0';
  88. return (T);
  89. }
  90. /*!
  91. * \brief Copies characters from the string F (not including the
  92. * terminating null character) into the string T.
  93. *
  94. * \param[out] T target string
  95. * \param[in] F source string
  96. *
  97. * \return T value
  98. */
  99. char *G_strmov(char *T, const char *F)
  100. {
  101. char *d = T;
  102. while (*F)
  103. *d++ = *F++;
  104. return (T);
  105. }
  106. /*!
  107. * \brief This copies characters from the string F (exactly n
  108. * characters) into the string T.
  109. *
  110. * The terminating null character is not explicitly written into the
  111. * string T.
  112. *
  113. * \param[out] T target string
  114. * \param[in] F source string
  115. * \param[in] n number of characters to copy
  116. *
  117. * \return T value
  118. */
  119. char *G_chrmov(char *T, const char *F, int n)
  120. {
  121. char *d = T;
  122. while (n--)
  123. *d++ = *F++;
  124. return (T);
  125. }
  126. /*!
  127. * \brief This copies characters from the string F into the string T.
  128. *
  129. * This function is similar to G_strcpy(), except that the
  130. * characters from F are concatenated or appended to the end of
  131. * T, instead of overwriting it. That is, the first character from
  132. * F overwrites the null character marking the end of T.
  133. *
  134. * \param[out] T target string
  135. * \param[in] F source string
  136. *
  137. * \return T value
  138. */
  139. char *G_strcat(char *T, const char *F)
  140. {
  141. G_strcpy(G_strend(T), F);
  142. return (T);
  143. }
  144. /*!
  145. * \brief This function is like G_strcat() except that not more than n
  146. * characters from F are appended to the end of T.
  147. *
  148. * This function is similar to G_strcpy(), except that the
  149. * characters from F are concatenated or appended to the end of
  150. * T, instead of overwriting it. That is, the first character from
  151. * F overwrites the null character marking the end of T.
  152. *
  153. * \param[out] T target string
  154. * \param[in] F source string
  155. * \param[in] n number of character to copy
  156. *
  157. * \return T value
  158. */
  159. char *G_chrcat(char *T, const char *F, int n)
  160. {
  161. G_chrcpy(G_strend(T), F, n);
  162. return (T);
  163. }
  164. /*!
  165. * \brief String compare ignoring case (upper or lower)
  166. *
  167. * Returning a value that has the same sign as the difference between
  168. * the first differing pair of characters
  169. *
  170. * \param[in] x first string to compare
  171. * \param[in] y second string to compare
  172. *
  173. * \return 0 the two strings are equal
  174. * \return -1, 1
  175. */
  176. int G_strcasecmp(const char *x, const char *y)
  177. {
  178. int xx, yy;
  179. if (!x)
  180. return y ? -1 : 0;
  181. if (!y)
  182. return x ? 1 : 0;
  183. while (*x && *y) {
  184. xx = *x++;
  185. yy = *y++;
  186. if (xx >= 'A' && xx <= 'Z')
  187. xx = xx + 'a' - 'A';
  188. if (yy >= 'A' && yy <= 'Z')
  189. yy = yy + 'a' - 'A';
  190. if (xx < yy)
  191. return -1;
  192. if (xx > yy)
  193. return 1;
  194. }
  195. if (*x)
  196. return 1;
  197. if (*y)
  198. return -1;
  199. return 0;
  200. }
  201. /*!
  202. * \brief Finds the first occurrence of the character C in the
  203. * null-terminated string beginning at mainString
  204. *
  205. * \param[in] mainString string where to find sub-string
  206. * \param[in] subString sub-string
  207. *
  208. * \return a pointer to the first occurrence of subString in
  209. * mainString
  210. * \return NULL if no occurrences are found
  211. */
  212. char *G_strstr(const char *mainString, const char *subString)
  213. {
  214. const char *p;
  215. const char *q;
  216. int length;
  217. p = subString;
  218. q = mainString;
  219. length = strlen(subString);
  220. do {
  221. while (*q != '\0' && *q != *p) { /* match 1st subString char */
  222. q++;
  223. }
  224. } while (*q != '\0' && strncmp(p, q, length) != 0 && q++);
  225. /* Short-circuit evaluation is your friend */
  226. if (*q == '\0') { /* ran off end of mainString */
  227. return NULL;
  228. }
  229. else {
  230. return (char *)q;
  231. }
  232. }
  233. /*!
  234. * \brief Copies the null-terminated string into a newly
  235. * allocated string. The string is allocated using G_malloc().
  236. *
  237. * \param[in] string the string to duplicate
  238. *
  239. * \return pointer to a string that is a duplicate of the string
  240. * given to G_strdup().
  241. * \return NULL if unable to allocate the required space
  242. */
  243. char *G_strdup(const char *string)
  244. {
  245. char *p;
  246. p = G_malloc(strlen(string) + 1);
  247. if (p != NULL) {
  248. strcpy(p, string);
  249. }
  250. return p;
  251. }
  252. /*!
  253. * \brief Replace all occurencies of character in string bug with new
  254. *
  255. * \param[in,out] bug base string
  256. * \param[in] character character to replace
  257. * \param[in] new new character
  258. *
  259. * \return bug string
  260. */
  261. char *G_strchg(char *bug, char character, char new)
  262. {
  263. char *help = bug;
  264. while (*help) {
  265. if (*help == character)
  266. *help = new;
  267. help++;
  268. }
  269. return bug;
  270. }
  271. /*!
  272. * \brief Replace all occurencies of old_str in buffer with new_str
  273. *
  274. * Code example:
  275. * \code
  276. * char *name;
  277. * name = G_str_replace ( inbuf, ".exe", "" );
  278. * ...
  279. * G_free (name);
  280. * \endcode
  281. *
  282. * \param[in,out] buffer main string
  283. * \param[in] old_str string to replace
  284. * \param[in] new_str new string
  285. *
  286. * \return the newly allocated string, input buffer is unchanged
  287. */
  288. char *G_str_replace(char *buffer, const char *old_str, const char *new_str)
  289. {
  290. char *B, *R;
  291. const char *N;
  292. char *replace;
  293. int count, len;
  294. /* Make sure old_str and new_str are not NULL */
  295. if (old_str == NULL || new_str == NULL)
  296. return G_strdup(buffer);
  297. /* Make sure buffer is not NULL */
  298. if (buffer == NULL)
  299. return NULL;
  300. /* Make sure old_str occurs */
  301. B = strstr(buffer, old_str);
  302. if (B == NULL)
  303. /* return NULL; */
  304. return G_strdup(buffer);
  305. if (strlen(new_str) > strlen(old_str)) {
  306. /* Count occurences of old_str */
  307. count = 0;
  308. len = strlen(old_str);
  309. B = buffer;
  310. while (B != NULL && *B != '\0') {
  311. B = G_strstr(B, old_str);
  312. if (B != NULL) {
  313. B += len;
  314. count++;
  315. }
  316. }
  317. len = count * (strlen(new_str) - strlen(old_str))
  318. + strlen(buffer);
  319. }
  320. else
  321. len = strlen(buffer);
  322. /* Allocate new replacement */
  323. replace = G_malloc(len + 1);
  324. if (replace == NULL)
  325. return NULL;
  326. /* Replace old_str with new_str */
  327. B = buffer;
  328. R = replace;
  329. len = strlen(old_str);
  330. while (*B != '\0') {
  331. if (*B == old_str[0] && strncmp(B, old_str, len) == 0) {
  332. N = new_str;
  333. while (*N != '\0')
  334. *R++ = *N++;
  335. B += len;
  336. }
  337. else {
  338. *R++ = *B++;
  339. }
  340. }
  341. *R = '\0';
  342. return replace;
  343. }
  344. /*!
  345. * \brief Removes all leading and trailing white space from string.
  346. *
  347. * \param[in,out] buf buffer to be worked on
  348. *
  349. * \return 0
  350. */
  351. int G_strip(char *buf)
  352. {
  353. register char *a, *b;
  354. /* remove leading white space */
  355. for (a = b = buf; *a == ' ' || *a == '\t'; a++) ;
  356. if (a != b)
  357. while ((*b++ = *a++)) ;
  358. /* remove trailing white space */
  359. for (a = buf; *a; a++) ;
  360. if (a != buf) {
  361. for (a--; *a == ' ' || *a == '\t'; a--) ;
  362. a++;
  363. *a = 0;
  364. }
  365. return 0;
  366. }
  367. /*!
  368. * \brief Chop leading and trailing white spaces:
  369. * \verbatim space, \f, \n, \r, \t, \v \endverbatim
  370. *
  371. * modified copy of G_squeeze(); RB March 2000 <Radim.Blazek@dhv.cz>
  372. *
  373. * \param line buffer to be worked on
  374. *
  375. * \return pointer to string
  376. */
  377. char *G_chop(char *line)
  378. {
  379. register char *f = line, *t = line;
  380. while (isspace(*f)) /* go to first non white-space char */
  381. f++;
  382. if (!*f) { /* no more chars in string */
  383. *t = '\0';
  384. return (line);
  385. }
  386. for (t = line; *t; t++) /* go to end */
  387. ;
  388. while (isspace(*--t)) ;
  389. *++t = '\0'; /* remove trailing white-spaces */
  390. t = line;
  391. while (*f) /* copy */
  392. *t++ = *f++;
  393. *t = '\0';
  394. return (line);
  395. }
  396. /*!
  397. * \brief Convert string to upper case
  398. *
  399. * \param[in,out] str pointer to string
  400. */
  401. void G_str_to_upper(char *str)
  402. {
  403. int i = 0;
  404. if (!str)
  405. return;
  406. while (str[i]) {
  407. str[i] = toupper(str[i]);
  408. i++;
  409. }
  410. }
  411. /*!
  412. * \brief Convert string to lower case
  413. *
  414. * \param[in,out] str pointer to string
  415. */
  416. void G_str_to_lower(char *str)
  417. {
  418. int i = 0;
  419. if (!str)
  420. return;
  421. while (str[i]) {
  422. str[i] = tolower(str[i]);
  423. i++;
  424. }
  425. }
  426. /*!
  427. * \brief Make string SQL compliant
  428. *
  429. * \param[in,out] str pointer to string
  430. *
  431. * \return number of changed characters
  432. */
  433. int G_str_to_sql(char *str)
  434. {
  435. int count;
  436. char *c;
  437. count = 0;
  438. if (!str)
  439. return 0;
  440. c = str;
  441. while (*c) {
  442. *c = toascii(*c);
  443. if (!(*c >= 'A' && *c <= 'Z') && !(*c >= 'a' && *c <= 'z') &&
  444. !(*c >= '0' && *c <= '9')) {
  445. *c = '_';
  446. count++;
  447. }
  448. c++;
  449. }
  450. c = str;
  451. if (!(*c >= 'A' && *c <= 'Z') && !(*c >= 'a' && *c <= 'z')) {
  452. *c = 'x';
  453. count++;
  454. }
  455. return count;
  456. }