~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to regex/split.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdio.h>
 
2
#include <string.h>
 
3
 
 
4
/*
 
5
 - split - divide a string into fields, like awk split()
 
6
 = int split(char *string, char *fields[], int nfields, char *sep);
 
7
 */
 
8
int                             /* number of fields, including overflow */
 
9
split(string, fields, nfields, sep)
 
10
char *string;
 
11
char *fields[];                 /* list is not NULL-terminated */
 
12
int nfields;                    /* number of entries available in fields[] */
 
13
char *sep;                      /* "" white, "c" single char, "ab" [ab]+ */
 
14
{
 
15
        register char *p = string;
 
16
        register char c;                        /* latest character */
 
17
        register char sepc = sep[0];
 
18
        register char sepc2;
 
19
        register int fn;
 
20
        register char **fp = fields;
 
21
        register char *sepp;
 
22
        register int trimtrail;
 
23
 
 
24
        /* white space */
 
25
        if (sepc == '\0') {
 
26
                while ((c = *p++) == ' ' || c == '\t')
 
27
                        continue;
 
28
                p--;
 
29
                trimtrail = 1;
 
30
                sep = (char*) " \t";    /* note, code below knows this is 2 long */
 
31
                sepc = ' ';
 
32
        } else
 
33
                trimtrail = 0;
 
34
        sepc2 = sep[1];         /* now we can safely pick this up */
 
35
 
 
36
        /* catch empties */
 
37
        if (*p == '\0')
 
38
                return(0);
 
39
 
 
40
        /* single separator */
 
41
        if (sepc2 == '\0') {
 
42
                fn = nfields;
 
43
                for (;;) {
 
44
                        *fp++ = p;
 
45
                        fn--;
 
46
                        if (fn == 0)
 
47
                                break;
 
48
                        while ((c = *p++) != sepc)
 
49
                                if (c == '\0')
 
50
                                        return(nfields - fn);
 
51
                        *(p-1) = '\0';
 
52
                }
 
53
                /* we have overflowed the fields vector -- just count them */
 
54
                fn = nfields;
 
55
                for (;;) {
 
56
                        while ((c = *p++) != sepc)
 
57
                                if (c == '\0')
 
58
                                        return(fn);
 
59
                        fn++;
 
60
                }
 
61
                /* not reached */
 
62
        }
 
63
 
 
64
        /* two separators */
 
65
        if (sep[2] == '\0') {
 
66
                fn = nfields;
 
67
                for (;;) {
 
68
                        *fp++ = p;
 
69
                        fn--;
 
70
                        while ((c = *p++) != sepc && c != sepc2)
 
71
                                if (c == '\0') {
 
72
                                        if (trimtrail && **(fp-1) == '\0')
 
73
                                                fn++;
 
74
                                        return(nfields - fn);
 
75
                                }
 
76
                        if (fn == 0)
 
77
                                break;
 
78
                        *(p-1) = '\0';
 
79
                        while ((c = *p++) == sepc || c == sepc2)
 
80
                                continue;
 
81
                        p--;
 
82
                }
 
83
                /* we have overflowed the fields vector -- just count them */
 
84
                fn = nfields;
 
85
                while (c != '\0') {
 
86
                        while ((c = *p++) == sepc || c == sepc2)
 
87
                                continue;
 
88
                        p--;
 
89
                        fn++;
 
90
                        while ((c = *p++) != '\0' && c != sepc && c != sepc2)
 
91
                                continue;
 
92
                }
 
93
                /* might have to trim trailing white space */
 
94
                if (trimtrail) {
 
95
                        p--;
 
96
                        while ((c = *--p) == sepc || c == sepc2)
 
97
                                continue;
 
98
                        p++;
 
99
                        if (*p != '\0') {
 
100
                                if (fn == nfields+1)
 
101
                                        *p = '\0';
 
102
                                fn--;
 
103
                        }
 
104
                }
 
105
                return(fn);
 
106
        }
 
107
 
 
108
        /* n separators */
 
109
        fn = 0;
 
110
        for (;;) {
 
111
                if (fn < nfields)
 
112
                        *fp++ = p;
 
113
                fn++;
 
114
                for (;;) {
 
115
                        c = *p++;
 
116
                        if (c == '\0')
 
117
                                return(fn);
 
118
                        sepp = sep;
 
119
                        while ((sepc = *sepp++) != '\0' && sepc != c)
 
120
                                continue;
 
121
                        if (sepc != '\0')       /* it was a separator */
 
122
                                break;
 
123
                }
 
124
                if (fn < nfields)
 
125
                        *(p-1) = '\0';
 
126
                for (;;) {
 
127
                        c = *p++;
 
128
                        sepp = sep;
 
129
                        while ((sepc = *sepp++) != '\0' && sepc != c)
 
130
                                continue;
 
131
                        if (sepc == '\0')       /* it wasn't a separator */
 
132
                                break;
 
133
                }
 
134
                p--;
 
135
        }
 
136
 
 
137
        /* not reached */
 
138
}
 
139
 
 
140
#ifdef TEST_SPLIT
 
141
 
 
142
 
 
143
/*
 
144
 * test program
 
145
 * pgm          runs regression
 
146
 * pgm sep      splits stdin lines by sep
 
147
 * pgm str sep  splits str by sep
 
148
 * pgm str sep n        splits str by sep n times
 
149
 */
 
150
int
 
151
main(argc, argv)
 
152
int argc;
 
153
char *argv[];
 
154
{
 
155
        char buf[512];
 
156
        register int n;
 
157
#       define  MNF     10
 
158
        char *fields[MNF];
 
159
 
 
160
        if (argc > 4)
 
161
                for (n = atoi(argv[3]); n > 0; n--) {
 
162
                        (void) strcpy(buf, argv[1]);
 
163
                }
 
164
        else if (argc > 3)
 
165
                for (n = atoi(argv[3]); n > 0; n--) {
 
166
                        (void) strcpy(buf, argv[1]);
 
167
                        (void) split(buf, fields, MNF, argv[2]);
 
168
                }
 
169
        else if (argc > 2)
 
170
                dosplit(argv[1], argv[2]);
 
171
        else if (argc > 1)
 
172
                while (fgets(buf, sizeof(buf), stdin) != NULL) {
 
173
                        buf[strlen(buf)-1] = '\0';      /* stomp newline */
 
174
                        dosplit(buf, argv[1]);
 
175
                }
 
176
        else
 
177
                regress();
 
178
 
 
179
        exit(0);
 
180
}
 
181
 
 
182
dosplit(string, seps)
 
183
char *string;
 
184
char *seps;
 
185
{
 
186
#       define  NF      5
 
187
        char *fields[NF];
 
188
        register int nf;
 
189
 
 
190
        nf = split(string, fields, NF, seps);
 
191
        print(nf, NF, fields);
 
192
}
 
193
 
 
194
print(nf, nfp, fields)
 
195
int nf;
 
196
int nfp;
 
197
char *fields[];
 
198
{
 
199
        register int fn;
 
200
        register int bound;
 
201
 
 
202
        bound = (nf > nfp) ? nfp : nf;
 
203
        printf("%d:\t", nf);
 
204
        for (fn = 0; fn < bound; fn++)
 
205
                printf("\"%s\"%s", fields[fn], (fn+1 < nf) ? ", " : "\n");
 
206
}
 
207
 
 
208
#define RNF     5               /* some table entries know this */
 
209
struct {
 
210
        char *str;
 
211
        char *seps;
 
212
        int nf;
 
213
        char *fi[RNF];
 
214
} tests[] = {
 
215
        "",             " ",    0,      { "" },
 
216
        " ",            " ",    2,      { "", "" },
 
217
        "x",            " ",    1,      { "x" },
 
218
        "xy",           " ",    1,      { "xy" },
 
219
        "x y",          " ",    2,      { "x", "y" },
 
220
        "abc def  g ",  " ",    5,      { "abc", "def", "", "g", "" },
 
221
        "  a bcd",      " ",    4,      { "", "", "a", "bcd" },
 
222
        "a b c d e f",  " ",    6,      { "a", "b", "c", "d", "e f" },
 
223
        " a b c d ",    " ",    6,      { "", "a", "b", "c", "d " },
 
224
 
 
225
        "",             " _",   0,      { "" },
 
226
        " ",            " _",   2,      { "", "" },
 
227
        "x",            " _",   1,      { "x" },
 
228
        "x y",          " _",   2,      { "x", "y" },
 
229
        "ab _ cd",      " _",   2,      { "ab", "cd" },
 
230
        " a_b  c ",     " _",   5,      { "", "a", "b", "c", "" },
 
231
        "a b c_d e f",  " _",   6,      { "a", "b", "c", "d", "e f" },
 
232
        " a b c d ",    " _",   6,      { "", "a", "b", "c", "d " },
 
233
 
 
234
        "",             " _~",  0,      { "" },
 
235
        " ",            " _~",  2,      { "", "" },
 
236
        "x",            " _~",  1,      { "x" },
 
237
        "x y",          " _~",  2,      { "x", "y" },
 
238
        "ab _~ cd",     " _~",  2,      { "ab", "cd" },
 
239
        " a_b  c~",     " _~",  5,      { "", "a", "b", "c", "" },
 
240
        "a b_c d~e f",  " _~",  6,      { "a", "b", "c", "d", "e f" },
 
241
        "~a b c d ",    " _~",  6,      { "", "a", "b", "c", "d " },
 
242
 
 
243
        "",             " _~-", 0,      { "" },
 
244
        " ",            " _~-", 2,      { "", "" },
 
245
        "x",            " _~-", 1,      { "x" },
 
246
        "x y",          " _~-", 2,      { "x", "y" },
 
247
        "ab _~- cd",    " _~-", 2,      { "ab", "cd" },
 
248
        " a_b  c~",     " _~-", 5,      { "", "a", "b", "c", "" },
 
249
        "a b_c-d~e f",  " _~-", 6,      { "a", "b", "c", "d", "e f" },
 
250
        "~a-b c d ",    " _~-", 6,      { "", "a", "b", "c", "d " },
 
251
 
 
252
        "",             "  ",   0,      { "" },
 
253
        " ",            "  ",   2,      { "", "" },
 
254
        "x",            "  ",   1,      { "x" },
 
255
        "xy",           "  ",   1,      { "xy" },
 
256
        "x y",          "  ",   2,      { "x", "y" },
 
257
        "abc def  g ",  "  ",   4,      { "abc", "def", "g", "" },
 
258
        "  a bcd",      "  ",   3,      { "", "a", "bcd" },
 
259
        "a b c d e f",  "  ",   6,      { "a", "b", "c", "d", "e f" },
 
260
        " a b c d ",    "  ",   6,      { "", "a", "b", "c", "d " },
 
261
 
 
262
        "",             "",     0,      { "" },
 
263
        " ",            "",     0,      { "" },
 
264
        "x",            "",     1,      { "x" },
 
265
        "xy",           "",     1,      { "xy" },
 
266
        "x y",          "",     2,      { "x", "y" },
 
267
        "abc def  g ",  "",     3,      { "abc", "def", "g" },
 
268
        "\t a bcd",     "",     2,      { "a", "bcd" },
 
269
        "  a \tb\t c ", "",     3,      { "a", "b", "c" },
 
270
        "a b c d e ",   "",     5,      { "a", "b", "c", "d", "e" },
 
271
        "a b\tc d e f", "",     6,      { "a", "b", "c", "d", "e f" },
 
272
        " a b c d e f ",        "",     6,      { "a", "b", "c", "d", "e f " },
 
273
 
 
274
        NULL,           NULL,   0,      { NULL },
 
275
};
 
276
 
 
277
regress()
 
278
{
 
279
        char buf[512];
 
280
        register int n;
 
281
        char *fields[RNF+1];
 
282
        register int nf;
 
283
        register int i;
 
284
        register int printit;
 
285
        register char *f;
 
286
 
 
287
        for (n = 0; tests[n].str != NULL; n++) {
 
288
                (void) strcpy(buf, tests[n].str);
 
289
                fields[RNF] = NULL;
 
290
                nf = split(buf, fields, RNF, tests[n].seps);
 
291
                printit = 0;
 
292
                if (nf != tests[n].nf) {
 
293
                        printf("split `%s' by `%s' gave %d fields, not %d\n",
 
294
                                tests[n].str, tests[n].seps, nf, tests[n].nf);
 
295
                        printit = 1;
 
296
                } else if (fields[RNF] != NULL) {
 
297
                        printf("split() went beyond array end\n");
 
298
                        printit = 1;
 
299
                } else {
 
300
                        for (i = 0; i < nf && i < RNF; i++) {
 
301
                                f = fields[i];
 
302
                                if (f == NULL)
 
303
                                        f = "(NULL)";
 
304
                                if (strcmp(f, tests[n].fi[i]) != 0) {
 
305
                                        printf("split `%s' by `%s', field %d is `%s', not `%s'\n",
 
306
                                                tests[n].str, tests[n].seps,
 
307
                                                i, fields[i], tests[n].fi[i]);
 
308
                                        printit = 1;
 
309
                                }
 
310
                        }
 
311
                }
 
312
                if (printit)
 
313
                        print(nf, RNF, fields);
 
314
        }
 
315
}
 
316
#endif