char CORD_fetch(CORD x, size_t i) { CORD_pos xpos; CORD_set_pos(xpos, x, i); if (!CORD_pos_valid(xpos)) ABORT("bad index?"); return(CORD_pos_fetch(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); }
void CORD__next(CORD_pos p) { size_t cur_pos = p[0].cur_pos + 1; struct CORD_pe * current_pe; CORD leaf; if (!CORD_pos_valid(p)) ABORT("CORD_next: invalid argument"); current_pe = &p[0].path[p[0].path_len]; leaf = current_pe -> pe_cord; /* Leaf is not a string or we're at end of leaf */ p[0].cur_pos = cur_pos; if (!CORD_IS_STRING(leaf)) { /* Function leaf */ struct Function * f = &(((CordRep *)leaf) -> function); size_t start_pos = current_pe -> pe_start_pos; size_t end_pos = start_pos + f -> len; if (cur_pos < end_pos) { /* Fill cache and return. */ size_t i; size_t limit = cur_pos + FUNCTION_BUF_SZ; CORD_fn fn = f -> fn; void * client_data = f -> client_data; if (limit > end_pos) { limit = end_pos; } for (i = cur_pos; i < limit; i++) { p[0].function_buf[i - cur_pos] = (*fn)(i - start_pos, client_data); } p[0].cur_start = cur_pos; p[0].cur_leaf = p[0].function_buf; p[0].cur_end = limit; return; } } /* End of leaf */ /* Pop the stack until we find two concatenation nodes with the */ /* same start position: this implies we were in left part. */ { while (p[0].path_len > 0 && current_pe[0].pe_start_pos != current_pe[-1].pe_start_pos) { p[0].path_len--; current_pe--; } if (p[0].path_len == 0) { p[0].path_len = CORD_POS_INVALID; return; } } p[0].path_len--; CORD__extend_path(p); }
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); } } }
char CORD__pos_fetch(CORD_pos p) { /* Leaf is a function node */ struct CORD_pe * pe; CORD leaf; struct Function * f; if (!CORD_pos_valid(p)) ABORT("CORD_pos_fetch: invalid argument"); pe = &p[0].path[p[0].path_len]; leaf = pe -> pe_cord; if (!IS_FUNCTION(leaf)) ABORT("CORD_pos_fetch: bad leaf"); f = &((CordRep *)leaf)->function; return ((*(f -> fn))(p[0].cur_pos - pe -> pe_start_pos, f -> client_data)); }
/* -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"); }