1 /* strtokc.c */
2
3 #include <string.h>
4 #include "Strn.h"
5
6 char *
strtokc(char * parsestr,const char * delims,char ** context)7 strtokc(char *parsestr, const char *delims, char **context)
8 {
9 char *cp;
10 const char *cp2;
11 char c, c2;
12 char *start;
13
14 if (parsestr == NULL)
15 start = *context;
16 else
17 start = parsestr;
18
19 if ((start == NULL) || (delims == NULL)) {
20 *context = NULL;
21 return NULL;
22 }
23
24 /* Eat leading delimiters. */
25 for (cp = start; ; ) {
26 next1:
27 c = *cp++;
28 if (c == '\0') {
29 /* No more tokens. */
30 *context = NULL;
31 return (NULL);
32 }
33 for (cp2 = delims; ; ) {
34 c2 = (char) *cp2++;
35 if (c2 == '\0') {
36 /* This character was not a delimiter.
37 * The token starts here.
38 */
39 start = cp - 1;
40 goto starttok;
41 }
42 if (c2 == c) {
43 /* This char was a delimiter. */
44 /* Skip it, look at next character. */
45 goto next1;
46 }
47 }
48 /*NOTREACHED*/
49 }
50
51 starttok:
52 for ( ; ; cp++) {
53 c = *cp;
54 if (c == '\0') {
55 /* Token is finished. */
56 *context = cp;
57 break;
58 }
59 for (cp2 = delims; ; ) {
60 c2 = (char) *cp2++;
61 if (c2 == '\0') {
62 /* This character was not a delimiter.
63 * Keep it as part of current token.
64 */
65 break;
66 }
67 if (c2 == c) {
68 /* This char was a delimiter. */
69 /* End of token. */
70 *cp++ = '\0';
71 *context = cp;
72 return (start);
73 }
74 }
75 }
76 return (start);
77 } /* strtokc */
78
79
80
81
82 /* Same as strtokc, only you specify the destination buffer to write
83 * the token in along with its size. strntokc will write to the dst
84 * buffer, always nul-terminating it.
85 *
86 * It also returns the length of the token, or zero if there was no
87 * token. This differs from strtokc, which returns a pointer to the
88 * token or NULL for no token.
89 */
90
91 int
strntokc(char * dstTokenStart,size_t tokenSize,char * parsestr,const char * delims,char ** context)92 strntokc(char *dstTokenStart, size_t tokenSize, char *parsestr, const char *delims, char **context)
93 {
94 char *cp;
95 const char *cp2;
96 char c, c2;
97 char *start;
98 int len;
99 char *dst, *lim;
100
101 dst = dstTokenStart;
102 lim = dst + tokenSize - 1; /* Leave room for nul byte. */
103
104 if (parsestr == NULL)
105 start = *context;
106 else
107 start = parsestr;
108
109 if ((start == NULL) || (delims == NULL)) {
110 *context = NULL;
111 goto done;
112 }
113
114 /* Eat leading delimiters. */
115 for (cp = start; ; ) {
116 next1:
117 c = *cp++;
118 if (c == '\0') {
119 /* No more tokens. */
120 *context = NULL;
121 goto done;
122 }
123 for (cp2 = delims; ; ) {
124 c2 = (char) *cp2++;
125 if (c2 == '\0') {
126 /* This character was not a delimiter.
127 * The token starts here.
128 */
129 start = cp - 1;
130 if (dst < lim)
131 *dst++ = c;
132 goto starttok;
133 }
134 if (c2 == c) {
135 /* This char was a delimiter. */
136 /* Skip it, look at next character. */
137 goto next1;
138 }
139 }
140 /*NOTREACHED*/
141 }
142
143 starttok:
144 for ( ; ; cp++) {
145 c = *cp;
146 if (c == '\0') {
147 /* Token is finished. */
148 *context = cp;
149 break;
150 }
151 for (cp2 = delims; ; ) {
152 c2 = (char) *cp2++;
153 if (c2 == '\0') {
154 /* This character was not a delimiter.
155 * Keep it as part of current token.
156 */
157 break;
158 }
159 if (c2 == c) {
160 /* This char was a delimiter. */
161 /* End of token. */
162 *cp++ = '\0';
163 *context = cp;
164 goto done;
165 }
166 }
167 if (dst < lim) /* Don't overrun token size. */
168 *dst++ = c;
169 }
170
171 done:
172 *dst = '\0';
173 len = (int) (dst - dstTokenStart); /* Return length of token. */
174
175 #if (STRN_ZERO_PAD == 1)
176 /* Pad with zeros. */
177 for (++dst; dst <= lim; )
178 *dst++ = 0;
179 #endif /* STRN_ZERO_PAD */
180
181 return (len);
182 } /* strntokc */
183
184
185
186
187 #ifdef TESTING_STRTOK
188 #include <stdio.h>
189
190 void
main(int argc,char ** argv)191 main(int argc, char **argv)
192 {
193 char buf[256];
194 int i;
195 char *t;
196 char token[8];
197 int tokenLen;
198 char *context;
199
200 if (argc < 3) {
201 fprintf(stderr, "Usage: test \"buffer,with,delims\" <delimiters>\n");
202 exit(1);
203 }
204 strcpy(buf, argv[1]);
205 i = 1;
206 t = strtok(buf, argv[2]);
207 if (t == NULL)
208 exit(0);
209 do {
210 printf("strtok %d=[%s] length=%d\n", i, t, (int) strlen(t));
211 t = strtok(NULL, argv[2]);
212 ++i;
213 } while (t != NULL);
214
215 printf("------------------------------------------------\n");
216 strcpy(buf, argv[1]);
217 i = 1;
218 t = strtokc(buf, argv[2], &context);
219 if (t == NULL)
220 exit(0);
221 do {
222 printf("strtokc %d=[%s] length=%d\n", i, t, (int) strlen(t));
223 t = strtokc(NULL, argv[2], &context);
224 ++i;
225 } while (t != NULL);
226
227 printf("------------------------------------------------\n");
228 strcpy(buf, argv[1]);
229 i = 1;
230 tokenLen = strntokc(token, sizeof(token), buf, argv[2], &context);
231 if (tokenLen <= 0)
232 exit(0);
233 do {
234 printf("strntokc %d=[%s] length=%d\n", i, token, tokenLen);
235 tokenLen = strntokc(token, sizeof(token), NULL, argv[2], &context);
236 ++i;
237 } while (tokenLen > 0);
238 exit(0);
239 }
240 #endif
241