/* It's very fast if there are few close misses. */ size_t CORD_str(CORD x, size_t start, CORD s) { CORD_pos xpos; size_t xlen = CORD_len(x); size_t slen; register size_t start_len; const char * s_start; unsigned long s_buf = 0; /* The first few characters of s */ unsigned long x_buf = 0; /* Start of candidate substring. */ /* Initialized only to make compilers */ /* happy. */ unsigned long mask = 0; register size_t i; register size_t match_pos; if (s == CORD_EMPTY) return(start); if (CORD_IS_STRING(s)) { s_start = s; slen = strlen(s); } else { s_start = CORD_to_char_star(CORD_substr(s, 0, sizeof(unsigned long))); slen = CORD_len(s); } if (xlen < start || xlen - start < slen) return(CORD_NOT_FOUND); start_len = slen; if (start_len > sizeof(unsigned long)) start_len = sizeof(unsigned long); CORD_set_pos(xpos, x, start); for (i = 0; i < start_len; i++) { mask <<= 8; mask |= 0xff; s_buf <<= 8; s_buf |= (unsigned char)s_start[i]; x_buf <<= 8; x_buf |= (unsigned char)CORD_pos_fetch(xpos); CORD_next(xpos); } for (match_pos = start; ; match_pos++) { if ((x_buf & mask) == s_buf) { if (slen == start_len || CORD_ncmp(x, match_pos + start_len, s, start_len, slen - start_len) == 0) { return(match_pos); } } if ( match_pos == xlen - slen ) { return(CORD_NOT_FOUND); } x_buf <<= 8; x_buf |= (unsigned char)CORD_pos_fetch(xpos); CORD_next(xpos); } }
int CORD_ncmp(CORD x, size_t x_start, CORD y, size_t y_start, size_t len) { CORD_pos xpos; CORD_pos ypos; register size_t count; register long avail, yavail; CORD_set_pos(xpos, x, x_start); CORD_set_pos(ypos, y, y_start); for(count = 0; count < len;) { if (!CORD_pos_valid(xpos)) { if (CORD_pos_valid(ypos)) { return(-1); } else { return(0); } } if (!CORD_pos_valid(ypos)) { return(1); } if ((avail = CORD_pos_chars_left(xpos)) <= 0 || (yavail = CORD_pos_chars_left(ypos)) <= 0) { register char xcurrent = CORD_pos_fetch(xpos); register char ycurrent = CORD_pos_fetch(ypos); if (xcurrent != ycurrent) return(xcurrent - ycurrent); CORD_next(xpos); CORD_next(ypos); count++; } else { /* process as many characters as we can */ register int result; if (avail > yavail) avail = yavail; count += avail; if (count > len) avail -= (count - len); result = strncmp(CORD_pos_cur_char_addr(xpos), CORD_pos_cur_char_addr(ypos), (size_t)avail); if (result != 0) return(result); CORD_pos_advance(xpos, (size_t)avail); CORD_pos_advance(ypos, (size_t)avail); } } return(0); }
int CORD_vsprintf(CORD * out, CORD format, va_list args) { CORD_ec result; register int count; register char current; CORD_pos pos; char conv_spec[CONV_SPEC_LEN + 1]; CORD_ec_init(result); for (CORD_set_pos(pos, format, 0); CORD_pos_valid(pos); CORD_next(pos)) { current = CORD_pos_fetch(pos); if (current == '%') { CORD_next(pos); if (!CORD_pos_valid(pos)) return(-1); current = CORD_pos_fetch(pos); if (current == '%') { CORD_ec_append(result, current); } else { int width, prec; int left_adj = 0; int long_arg = 0; CORD arg; size_t len; if (extract_conv_spec(pos, conv_spec, &width, &prec, &left_adj, &long_arg) < 0) { return(-1); } current = CORD_pos_fetch(pos); switch(current) { case 'n': /* Assign length to next arg */ if (long_arg == 0) { int * pos_ptr; pos_ptr = va_arg(args, int *); *pos_ptr = ec_len(result); } else if (long_arg > 0) { long * pos_ptr; pos_ptr = va_arg(args, long *); *pos_ptr = ec_len(result); } else {
int CORD_cmp(CORD x, CORD y) { CORD_pos xpos; CORD_pos ypos; register size_t avail, yavail; if (y == CORD_EMPTY) return(x != CORD_EMPTY); if (x == CORD_EMPTY) return(-1); if (CORD_IS_STRING(y) && CORD_IS_STRING(x)) return(strcmp(x,y)); CORD_set_pos(xpos, x, 0); CORD_set_pos(ypos, y, 0); for(;;) { if (!CORD_pos_valid(xpos)) { if (CORD_pos_valid(ypos)) { return(-1); } else { return(0); } } if (!CORD_pos_valid(ypos)) { return(1); } if ((avail = CORD_pos_chars_left(xpos)) <= 0 || (yavail = CORD_pos_chars_left(ypos)) <= 0) { register char xcurrent = CORD_pos_fetch(xpos); register char ycurrent = CORD_pos_fetch(ypos); if (xcurrent != ycurrent) return(xcurrent - ycurrent); CORD_next(xpos); CORD_next(ypos); } else { /* process as many characters as we can */ register int result; if (avail > yavail) avail = yavail; result = strncmp(CORD_pos_cur_char_addr(xpos), CORD_pos_cur_char_addr(ypos), avail); if (result != 0) return(result); CORD_pos_advance(xpos, avail); CORD_pos_advance(ypos, avail); } } }
/* -1 if 'h' is present. */ static int extract_conv_spec(CORD_pos source, char *buf, int * width, int *prec, int *left, int * long_arg) { register int result = 0; register int current_number = 0; register int saw_period = 0; register int saw_number = 0; register int chars_so_far = 0; register char current; *width = NONE; buf[chars_so_far++] = '%'; while(CORD_pos_valid(source)) { if (chars_so_far >= CONV_SPEC_LEN) return(-1); current = CORD_pos_fetch(source); buf[chars_so_far++] = current; switch(current) { case '*': saw_number = 1; current_number = VARIABLE; break; case '0': if (!saw_number) { /* Zero fill flag; ignore */ break; } /* otherwise fall through: */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': saw_number = 1; current_number *= 10; current_number += current - '0'; break; case '.': saw_period = 1; if(saw_number) { *width = current_number; saw_number = 0; } current_number = 0; break; case 'l': case 'L': *long_arg = 1; current_number = 0; break; case 'h': *long_arg = -1; current_number = 0; break; case ' ': case '+': case '#': current_number = 0; break; case '-': *left = 1; current_number = 0; break; case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': case 'f': case 'e': case 'E': case 'g': case 'G': case 'c': case 'C': case 's': case 'S': case 'p': case 'n': case 'r': goto done; default: return(-1); } CORD_next(source); } return(-1); done: if (saw_number) { if (saw_period) { *prec = current_number; } else { *prec = NONE; *width = current_number; } } else { *prec = NONE; } buf[chars_so_far] = '\0'; return(result); }
void test_basics(void) { CORD x = CORD_from_char_star("ab"); register int i; char c; CORD y; CORD_pos p; x = CORD_cat(x,x); if (x == CORD_EMPTY) ABORT("CORD_cat(x,x) returned empty cord"); if (!CORD_IS_STRING(x)) ABORT("short cord should usually be a string"); if (strcmp(x, "abab") != 0) ABORT("bad CORD_cat result"); for (i = 1; i < 16; i++) { x = CORD_cat(x,x); } x = CORD_cat(x,"c"); if (CORD_len(x) != 128*1024+1) ABORT("bad length"); count = 0; if (CORD_iter5(x, 64*1024-1, test_fn, CORD_NO_FN, (void *)13) == 0) { ABORT("CORD_iter5 failed"); } if (count != 64*1024 + 2) ABORT("CORD_iter5 failed"); count = 0; CORD_set_pos(p, x, 64*1024-1); while(CORD_pos_valid(p)) { (void) test_fn(CORD_pos_fetch(p), (void *)13); CORD_next(p); } if (count != 64*1024 + 2) ABORT("Position based iteration failed"); y = CORD_substr(x, 1023, 5); if (!y) ABORT("CORD_substr returned NULL"); if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string"); if (strcmp(y, "babab") != 0) ABORT("bad CORD_substr result"); y = CORD_substr(x, 1024, 8); if (!y) ABORT("CORD_substr returned NULL"); if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string"); if (strcmp(y, "abababab") != 0) ABORT("bad CORD_substr result"); y = CORD_substr(x, 128*1024-1, 8); if (!y) ABORT("CORD_substr returned NULL"); if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string"); if (strcmp(y, "bc") != 0) ABORT("bad CORD_substr result"); x = CORD_balance(x); if (CORD_len(x) != 128*1024+1) ABORT("bad length"); count = 0; if (CORD_iter5(x, 64*1024-1, test_fn, CORD_NO_FN, (void *)13) == 0) { ABORT("CORD_iter5 failed"); } if (count != 64*1024 + 2) ABORT("CORD_iter5 failed"); y = CORD_substr(x, 1023, 5); if (!y) ABORT("CORD_substr returned NULL"); if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string"); if (strcmp(y, "babab") != 0) ABORT("bad CORD_substr result"); y = CORD_from_fn(id_cord_fn, 0, 13); i = 0; CORD_set_pos(p, y, i); while(CORD_pos_valid(p)) { c = CORD_pos_fetch(p); if(c != i) ABORT("Traversal of function node failed"); CORD_next(p); i++; } if (i != 13) ABORT("Bad apparent length for function node"); }