1 /* Strntok.c */ 2 3 #include <string.h> 4 #include "Strn.h" 5 6 /* This version of Strtok differs from the regular ANSI strtok in that 7 * an empty token can be returned, and consecutive delimiters are not 8 * ignored like ANSI does. Example: 9 * 10 * Parse String = ",,mike,gleason,-West Interactive,402-573-1000" 11 * Delimiters = ",-" 12 * 13 * (ANSI strtok:) 14 * strtok 1=[mike] length=4 15 * strtok 2=[gleason] length=7 16 * strtok 3=[West Interactive] length=16 17 * strtok 4=[402] length=3 18 * strtok 5=[573] length=3 19 * strtok 6=[1000] length=4 20 * 21 * (Strtok:) 22 * Strtok 1=[] length=0 23 * Strtok 2=[] length=0 24 * Strtok 3=[mike] length=4 25 * Strtok 4=[gleason] length=7 26 * Strtok 5=[] length=0 27 * Strtok 6=[West Interactive] length=16 28 * Strtok 7=[402] length=3 29 * Strtok 8=[573] length=3 30 * Strtok 9=[1000] length=4 31 * 32 */ 33 34 char * 35 Strtok(char *buf, const char *delims) 36 { 37 static char *p = NULL; 38 char *start, *end; 39 40 if (buf != NULL) { 41 p = buf; 42 } else { 43 if (p == NULL) 44 return (NULL); /* No more tokens. */ 45 } 46 for (start = p, end = p; ; end++) { 47 if (*end == '\0') { 48 p = NULL; /* This is the last token. */ 49 break; 50 } 51 if (strchr(delims, (int) *end) != NULL) { 52 *end++ = '\0'; 53 p = end; 54 break; 55 } 56 } 57 return (start); 58 } /* Strtok */ 59 60 61 62 63 /* This is a bounds-safe version of Strtok, where you also pass a pointer 64 * to the token to write into, and its size. Using the example above, 65 * with a char token[8], you get the following. Notice that the token 66 * is not overrun, and is always nul-terminated: 67 * 68 * Strntok 1=[] length=0 69 * Strntok 2=[] length=0 70 * Strntok 3=[mike] length=4 71 * Strntok 4=[gleason] length=7 72 * Strntok 5=[] length=0 73 * Strntok 6=[West In] length=7 74 * Strntok 7=[402] length=3 75 * Strntok 8=[573] length=3 76 * Strntok 9=[1000] length=4 77 */ 78 79 int 80 Strntok(char *dstTokenStart, size_t tokenSize, char *buf, const char *delims) 81 { 82 static char *p = NULL; 83 char *end; 84 char *lim; 85 char *dst; 86 int len; 87 88 dst = dstTokenStart; 89 lim = dst + tokenSize - 1; /* Leave room for nul byte. */ 90 91 if (buf != NULL) { 92 p = buf; 93 } else { 94 if (p == NULL) { 95 *dst = '\0'; 96 return (-1); /* No more tokens. */ 97 } 98 } 99 100 for (end = p; ; end++) { 101 if (*end == '\0') { 102 p = NULL; /* This is the last token. */ 103 break; 104 } 105 if (strchr(delims, (int) *end) != NULL) { 106 ++end; 107 p = end; 108 break; 109 } 110 if (dst < lim) /* Don't overrun token size. */ 111 *dst++ = *end; 112 } 113 *dst = '\0'; 114 len = (int) (dst - dstTokenStart); /* Return length of token. */ 115 116 #if (STRN_ZERO_PAD == 1) 117 /* Pad with zeros. */ 118 for (++dst; dst <= lim; ) 119 *dst++ = 0; 120 #endif /* STRN_ZERO_PAD */ 121 122 return (len); 123 } /* Strntok */ 124 125 126 127 #ifdef TESTING_STRTOK 128 #include <stdio.h> 129 130 void 131 main(int argc, char **argv) 132 { 133 char buf[256]; 134 int i; 135 char *t; 136 char token[8]; 137 int tokenLen; 138 139 if (argc < 3) { 140 fprintf(stderr, "Usage: test \"buffer,with,delims\" <delimiters>\n"); 141 exit(1); 142 } 143 strcpy(buf, argv[1]); 144 i = 1; 145 t = strtok(buf, argv[2]); 146 if (t == NULL) 147 exit(0); 148 do { 149 printf("strtok %d=[%s] length=%d\n", i, t, (int) strlen(t)); 150 t = strtok(NULL, argv[2]); 151 ++i; 152 } while (t != NULL); 153 154 printf("------------------------------------------------\n"); 155 strcpy(buf, argv[1]); 156 i = 1; 157 t = Strtok(buf, argv[2]); 158 if (t == NULL) 159 exit(0); 160 do { 161 printf("Strtok %d=[%s] length=%d\n", i, t, (int) strlen(t)); 162 t = Strtok(NULL, argv[2]); 163 ++i; 164 } while (t != NULL); 165 166 printf("------------------------------------------------\n"); 167 strcpy(buf, argv[1]); 168 i = 1; 169 tokenLen = Strntok(token, sizeof(token), buf, argv[2]); 170 if (tokenLen < 0) 171 exit(0); 172 do { 173 printf("Strntok %d=[%s] length=%d\n", i, token, tokenLen); 174 tokenLen = Strntok(token, sizeof(token), NULL, argv[2]); 175 ++i; 176 } while (tokenLen >= 0); 177 exit(0); 178 } 179 #endif 180