strtok_r.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*--------------------------------------------------------------------------*/
  2. /* */
  3. /* File: STRTOK_R.C */
  4. /* Created: 20-September-2002 */
  5. /* Author: Peter Scandrett */
  6. /* Description: Module to provide a reentrant version of the 'C' */
  7. /* function STRTOK. */
  8. /* */
  9. /*--------------------------------------------------------------------------*/
  10. /* */
  11. /* Copyright (C) 2002 by ALSTOM Australia Limited. All rights reserved. */
  12. /* */
  13. /* Redistribution and use in source and binary forms, with or without */
  14. /* modification, are permitted provided that the following conditions */
  15. /* are met: */
  16. /* 1. Redistributions of source code must retain the above copyright */
  17. /* notice and this list of conditions. */
  18. /* 2. Neither the name of ALSTOM Australia Limited nor the names of its */
  19. /* contributors may be used to endorse or promote products derived */
  20. /* from this software. */
  21. /* */
  22. /* THIS SOFTWARE IS PROVIDED BY ALSTOM AUSTRALIA LIMITED AND CONTRIBUTORS */
  23. /* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
  24. /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
  25. /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALSTOM */
  26. /* AUSTRALIA LIMITED OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */
  27. /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */
  28. /* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS */
  29. /* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED */
  30. /* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */
  31. /* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF */
  32. /* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH */
  33. /* DAMAGE. */
  34. /* */
  35. /*--------------------------------------------------------------------------*/
  36. /*
  37. * $Log$
  38. * Revision 1.7 2008/02/15 17:13:16 haraldkipp
  39. * Use configurable constant attribute.
  40. *
  41. * Revision 1.6 2006/10/08 16:48:08 haraldkipp
  42. * Documentation fixed
  43. *
  44. * Revision 1.5 2004/07/27 19:28:51 drsung
  45. * Implementation of strtok_r adjusted to the POSIX 1c standard.
  46. *
  47. * Revision 1.4 2003/12/16 22:34:41 drsung
  48. * Portability issues
  49. *
  50. */
  51. #include <stdlib.h>
  52. #include <string.h>
  53. #include "strtok_r.h"
  54. /*!
  55. * \addtogroup xgCrtMisc
  56. *
  57. * The functions strtok_r(), strsep_r() and strsep_rs() are intended as a
  58. * replacement for the strtok() function. While the strtok() function should
  59. * be preferred for portability reasons (it conforms to ISO/IEC 9899:1990
  60. * ("ISO C89")) it may not be able to be used in a multi-threaded environment
  61. * (that is it is not reentrant). Functions strsep_r() and strsep_rs() can
  62. * handle empty fields, (i.e. detect fields delimited by two adjacent
  63. * delimiter characters). Function strsep() first appeared in 4.4BSD.
  64. */
  65. /*@{*/
  66. /*--------------------------------------------------------------------------*/
  67. static char *end_tok(char **pp_str, const char *p_delim, char *p_sep)
  68. {
  69. register const char *sp;
  70. char *p_tok;
  71. char *p_ch;
  72. /* Use a local pointer. */
  73. p_ch = *pp_str;
  74. /* Scan for next deliminator. */
  75. p_tok = p_ch;
  76. while (*p_ch != 0) {
  77. for (sp = p_delim; *sp != 0; sp++) {
  78. if (*sp == *p_ch) {
  79. if (p_sep != NULL) {
  80. /* Save terminator. */
  81. *p_sep = *p_ch;
  82. }
  83. *p_ch++ = 0;
  84. *pp_str = p_ch;
  85. return p_tok;
  86. }
  87. }
  88. p_ch++;
  89. }
  90. /* At end of string, so exit, but return last token. */
  91. *pp_str = p_ch;
  92. return p_tok;
  93. }
  94. /*--------------------------------------------------------------------------*/
  95. /*!
  96. * \brief Thread safe variant of strsep.
  97. *
  98. * This function is identical in operation to strsep_r(), except it returns the
  99. * deliminating character.
  100. */
  101. char *strsep_rs(char **pp_str, const char *p_delim, char *p_sep)
  102. {
  103. char *p_ch;
  104. /* Assume terminator was end of string. */
  105. if (p_sep != NULL)
  106. *p_sep = 0;
  107. /* Check not passed a NULL. */
  108. if (pp_str == NULL)
  109. return NULL;
  110. /* Use a local pointer. */
  111. p_ch = *pp_str;
  112. if (p_ch == NULL)
  113. return NULL;
  114. if (*p_ch == 0)
  115. return NULL;
  116. /* Check a valid delimiter string. */
  117. if ((p_delim == NULL) || (*p_delim == 0)) {
  118. *pp_str = NULL;
  119. return p_ch;
  120. }
  121. /* Scan for next deliminator. */
  122. return end_tok(pp_str, p_delim, p_sep);
  123. }
  124. /*--------------------------------------------------------------------------*/
  125. /*!
  126. * \brief Thread safe version of strsep.
  127. *
  128. * This function locates, in the string referenced by *str, the first occurrence of
  129. * any character in the string delim (or the terminating `\\0' character) and
  130. * replaces it with a `\\0'. The location of the next character after the delimiter
  131. * character (or NULL, if the end of the string was reached) is stored in *str.
  132. * The original value of *str is returned.
  133. *
  134. * An "empty" field, i.e. one caused by two adjacent delimiter characters, can be
  135. * detected by comparing the location referenced by the pointer returned in *str
  136. * to `\\0'.
  137. *
  138. * If *str is initially NULL, strsep_r() returns NULL.
  139. *
  140. * If delim is NULL or the empty string, strsep_r() returns *str.
  141. */
  142. char *strsep_r(char **pp_str, const char *p_delim)
  143. {
  144. return strsep_rs(pp_str, p_delim, NULL);
  145. }
  146. /*--------------------------------------------------------------------------*/
  147. /*!
  148. * \brief Thread safe version of strtok.
  149. *
  150. * This function locates, in the string referenced by *s, the occurrence of
  151. * any character in the string delim (or the terminating `\\0' character) and
  152. * replaces them with a `\\0'. The location of the next character after the
  153. * delimiter character (or NULL, if the end of the string was reached) is
  154. * stored in *save_ptr. The first character not a delimiter character from
  155. * the original value of *s is returned.
  156. *
  157. * \deprecated This function is supported by avrlibc, which uses different
  158. * parameters. It's still available for ICCAVR, but should be
  159. * avoided for portability reasons.
  160. */
  161. #ifdef __IMAGECRAFT__
  162. /* Parse S into tokens separated by characters in DELIM.
  163. If S is NULL, the saved pointer in SAVE_PTR is used as
  164. the next starting point. For example:
  165. char s[] = "-abc-=-def";
  166. char *sp;
  167. x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def"
  168. x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL
  169. x = strtok_r(NULL, "=", &sp); // x = NULL
  170. // s = "abc\\0-def\\0"
  171. */
  172. char *strtok_r(char *s, const char *delim, char **save_ptr)
  173. {
  174. char *token;
  175. if (s == NULL)
  176. s = *save_ptr;
  177. /* Scan leading delimiters. */
  178. s += strspn(s, delim);
  179. if (*s == '\0')
  180. return NULL;
  181. /* Find the end of the token. */
  182. token = s;
  183. s = strpbrk(token, delim);
  184. if (s == NULL)
  185. /* This token finishes the string. */
  186. *save_ptr = strchr(token, '\0');
  187. else {
  188. /* Terminate the token and make *SAVE_PTR point past it. */
  189. *s = '\0';
  190. *save_ptr = s + 1;
  191. }
  192. return token;
  193. }
  194. #endif /*__IMAGECRAFT__ */
  195. /*@}*/
  196. /*-------------------------- end of file STRTOK_R.C ------------------------*/