ssplit.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*********************************************************************
  2. *
  3. * File : $Source: /cvsroot/ijbswa/current/ssplit.c,v $
  4. *
  5. * Purpose : A function to split a string at specified delimiters.
  6. *
  7. * Copyright : Written by and Copyright (C) 2001-2012 the
  8. * Privoxy team. https://www.privoxy.org/
  9. *
  10. * Based on the Internet Junkbuster originally written
  11. * by and Copyright (C) 1997 Anonymous Coders and
  12. * Junkbusters Corporation. http://www.junkbusters.com
  13. *
  14. * This program is free software; you can redistribute it
  15. * and/or modify it under the terms of the GNU General
  16. * Public License as published by the Free Software
  17. * Foundation; either version 2 of the License, or (at
  18. * your option) any later version.
  19. *
  20. * This program is distributed in the hope that it will
  21. * be useful, but WITHOUT ANY WARRANTY; without even the
  22. * implied warranty of MERCHANTABILITY or FITNESS FOR A
  23. * PARTICULAR PURPOSE. See the GNU General Public
  24. * License for more details.
  25. *
  26. * The GNU General Public License should be included with
  27. * this file. If not, you can view it at
  28. * http://www.gnu.org/copyleft/gpl.html
  29. * or write to the Free Software Foundation, Inc., 59
  30. * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  31. *
  32. *********************************************************************/
  33. #include "config.h"
  34. #include <string.h>
  35. #include <stdlib.h>
  36. #include <assert.h>
  37. #include "ssplit.h"
  38. #include "miscutil.h"
  39. /*********************************************************************
  40. *
  41. * Function : ssplit
  42. *
  43. * Description : Split a string using delimiters in `delim'. Results
  44. * go into `vec'.
  45. *
  46. * Parameters :
  47. * 1 : str = string to split. Will be split in place
  48. * (i.e. do not free until you've finished with vec,
  49. * previous contents will be trashed by the call).
  50. * 2 : delim = array of delimiters (if NULL, uses " \t").
  51. * 3 : vec[] = results vector (aka. array) [out]
  52. * 4 : vec_len = number of usable slots in the vector (aka. array size)
  53. *
  54. * Returns : -1 => Error: vec_len is too small to hold all the
  55. * data, or str == NULL.
  56. * >=0 => the number of fields put in `vec'.
  57. * On error, vec and str may still have been overwritten.
  58. *
  59. *********************************************************************/
  60. int ssplit(char *str, const char *delim, char *vec[], size_t vec_len)
  61. {
  62. unsigned char is_delim[256];
  63. unsigned char char_type;
  64. int vec_count = 0;
  65. enum char_type {
  66. WANTED = 0,
  67. SEPARATOR = 1,
  68. TERMINATOR = 2,
  69. };
  70. if (!str)
  71. {
  72. return(-1);
  73. }
  74. /* Build is_delim array */
  75. memset(is_delim, '\0', sizeof(is_delim));
  76. if (!delim)
  77. {
  78. delim = " \t"; /* default field separators */
  79. }
  80. while (*delim)
  81. {
  82. is_delim[(unsigned)(unsigned char)*delim++] = SEPARATOR;
  83. }
  84. is_delim[(unsigned)(unsigned char)'\0'] = TERMINATOR;
  85. is_delim[(unsigned)(unsigned char)'\n'] = TERMINATOR;
  86. /* Parse string */
  87. /* Skip leading separators. XXX: Why do they matter? */
  88. while (is_delim[(unsigned)(unsigned char)*str] == SEPARATOR)
  89. {
  90. str++;
  91. }
  92. /* The first pointer is the beginning of string */
  93. if (is_delim[(unsigned)(unsigned char)*str] == WANTED)
  94. {
  95. /*
  96. * The first character in this field is not a
  97. * delimiter or the end of string, so save it.
  98. */
  99. if (vec_count >= vec_len)
  100. {
  101. return(-1); /* overflow */
  102. }
  103. vec[vec_count++] = str;
  104. }
  105. while ((char_type = is_delim[(unsigned)(unsigned char)*str]) != TERMINATOR)
  106. {
  107. if (char_type == SEPARATOR)
  108. {
  109. /* the char is a separator */
  110. /* null terminate the substring */
  111. *str++ = '\0';
  112. /* Check if we want to save this field */
  113. if (is_delim[(unsigned)(unsigned char)*str] == WANTED)
  114. {
  115. /*
  116. * The first character in this field is not a
  117. * delimiter or the end of string. So save it.
  118. */
  119. if (vec_count >= vec_len)
  120. {
  121. return(-1); /* overflow */
  122. }
  123. vec[vec_count++] = str;
  124. }
  125. }
  126. else
  127. {
  128. str++;
  129. }
  130. }
  131. /* null terminate the substring */
  132. /* XXX: this shouldn't be necessary, so assert that it isn't. */
  133. assert(*str == '\0');
  134. *str = '\0';
  135. return(vec_count);
  136. }
  137. /*
  138. Local Variables:
  139. tab-width: 3
  140. end:
  141. */