1054
|
1 /* Standard system headers */
|
|
2 #include <stdlib.h>
|
|
3 #include <string.h>
|
|
4
|
|
5 /*
|
|
6 * memtok differs from strtok in a few ways:
|
|
7 * The pointer to the buffer to be scanned AND the pointer to the delimiters are NOT NULL terminated
|
|
8 * strings but are each a pair of a pointer and byte count (so that NIL characters can be contained
|
|
9 * in either of these buffers!
|
|
10 *
|
|
11 * Also memtok does not replace the "found" delimiter with a NIL character, but places the number
|
|
12 * of bytes delimited by that delimiter into the location of the size_t pointer to by found.
|
|
13 *
|
|
14 * The whole **real** point of this function was that strtok skips any repeating delimiters, but we
|
|
15 * need a function that retuns "empty strings" should there be two delimiters in a row.
|
|
16 *
|
|
17 * For some sense of consistency, the byte count of the buffer to be searched through is ALSO ignored
|
|
18 * by memtok iff the buffer to be scanned is NULL
|
|
19 *
|
|
20 * Here's an example:
|
|
21 *
|
|
22 * size_t found = 0;
|
|
23 * char *tok = 0, *buffer = malloc (COUNT);
|
|
24 * fill_buffer_with_some_data (buffer, COUNT);
|
|
25 * tok = memtok (buffer, COUNT, "\000\002", 2, &found);
|
|
26 *
|
|
27 * if tok != NULL then the bytes from tok to (tok + found) are the token
|
|
28 * You can then look for more tokens with:
|
|
29 *
|
|
30 * tok = memtok (NULL, 0, "\000\002", 2, &found);
|
|
31 *
|
|
32 * If tmp == NULL noone of the delimiters were found, however tmp can != NULL and found CAN == 0
|
|
33 *
|
|
34 * This means that although a delimiter was found it was immediately preceded by another delimiter and
|
|
35 * thus delimited an empty token.
|
|
36 *
|
|
37 * ( As it happens, if one of the delimiters you want to search for is a NIL character, you can put the
|
|
38 * other delimiter characters in a string literal and "lie" about how many delimiter characters there are
|
|
39 * because all string literals are NIL terminated!
|
|
40 *
|
|
41 * Therefor the above example could have been written:
|
|
42 * tok = memtok (buffer, COUNT, "\002", 2, &found);
|
|
43 *
|
|
44 * There are also two supplimentary functions that make using these tokens easier
|
|
45 *
|
|
46 * memdup is akin to strdup except that instead of it looking for a NIL termination character
|
|
47 * it simply mallocs copies the specified number of bytes
|
|
48 *
|
|
49 * memdupasstr does as memdup except that it mallocs 1 more byte and makes it a NIL char so that you
|
|
50 * can treat it as a string (as long as you're sure that the memory being described by the pointer and
|
|
51 * byte count don't already contain any NIL characters)
|
|
52 *
|
|
53 */
|
|
54
|
|
55 /**********************************************************************************************************************************/
|
|
56 /* Interface (global) functions */
|
|
57 /**********************************************************************************************************************************/
|
|
58 char *memtok(char *m, size_t bytes, const char *delims, size_t delim_count,
|
|
59 size_t * found)
|
|
60 {
|
|
61 static char *mem = 0, *c = 0;
|
|
62 static size_t offset = 0, offset_now = 0, limit = 0;
|
|
63
|
|
64 if (0 != m)
|
|
65 {
|
|
66 mem = m;
|
|
67 offset = 0;
|
|
68 limit = bytes;
|
|
69 }
|
|
70
|
|
71 offset_now = offset;
|
|
72
|
|
73 for (c = mem; offset < limit; ++offset, ++c)
|
|
74 {
|
|
75 if (0 != memchr(delims, *c, delim_count))
|
|
76 {
|
|
77 static char *ret = 0;
|
|
78
|
|
79 ret = mem;
|
|
80 mem = c + 1;
|
|
81 *found = offset - offset_now;
|
|
82 offset_now = offset + 1;
|
|
83 return ret;
|
|
84 }
|
|
85 }
|
|
86
|
|
87 return 0;
|
|
88 }
|
|
89
|
|
90 char *memdup(const char *mem, size_t bytes)
|
|
91 {
|
|
92 char *dup = 0;
|
|
93
|
|
94 if (0 < bytes && 0 != mem)
|
|
95 {
|
|
96 dup = malloc(bytes);
|
|
97 memcpy(dup, mem, bytes);
|
|
98 }
|
|
99
|
|
100 return dup;
|
|
101 }
|
|
102
|
|
103 char *memdupasstr(const char *mem, size_t bytes)
|
|
104 {
|
|
105 char *string = 0;
|
|
106
|
|
107 if (0 < bytes && 0 != mem)
|
|
108 {
|
|
109 string = memdup(mem, bytes + 1);
|
|
110 string[bytes] = '\0';
|
|
111 }
|
|
112
|
|
113 return string;
|
|
114 }
|