Annotation of embedaddon/php/ext/ereg/regex/split.c, revision 1.1
1.1 ! misho 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 = " \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
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>