/* See cord.h for definition. We assume i is in range. */ int CORD_iter5(CORD x, size_t i, CORD_iter_fn f1, CORD_batched_iter_fn f2, void * client_data) { if (x == 0) return(0); if (CORD_IS_STRING(x)) { register const char *p = x+i; if (*p == '\0') ABORT("2nd arg to CORD_iter5 too big"); if (f2 != CORD_NO_FN) { return((*f2)(p, client_data)); } else { while (*p) { if ((*f1)(*p, client_data)) return(1); p++; } return(0); } } else if (IS_CONCATENATION(x)) { register struct Concatenation * conc = &(((CordRep *)x) -> concatenation); if (i > 0) { register size_t left_len = LEFT_LEN(conc); if (i >= left_len) { return(CORD_iter5(conc -> right, i - left_len, f1, f2, client_data)); } } if (CORD_iter5(conc -> left, i, f1, f2, client_data)) { return(1); } return(CORD_iter5(conc -> right, 0, f1, f2, client_data)); } else /* function */ { register struct Function * f = &(((CordRep *)x) -> function); register size_t j; register size_t lim = f -> len; for (j = i; j < lim; j++) { if ((*f1)((*(f -> fn))(j, f -> client_data), client_data)) { return(1); } } return(0); } }
/* of the final tree. */ void CORD_balance_insert(CORD x, size_t len, ForestElement * forest) { int depth; if (CORD_IS_STRING(x)) { CORD_add_forest(forest, x, len); } else if (IS_CONCATENATION(x) && ((depth = DEPTH(x)) >= MAX_DEPTH || len < min_len[depth])) { struct Concatenation * conc = &(((CordRep *)x) -> concatenation); size_t left_len = LEFT_LEN(conc); CORD_balance_insert(conc -> left, left_len, forest); CORD_balance_insert(conc -> right, len - left_len, forest); } else /* function or balanced */ { CORD_add_forest(forest, x, len); } }
int CORD_riter4(CORD x, size_t i, CORD_iter_fn f1, void * client_data) { if (x == 0) return(0); if (CORD_IS_STRING(x)) { register const char *p = x + i; register char c; for(;;) { c = *p; if (c == '\0') ABORT("2nd arg to CORD_riter4 too big"); if ((*f1)(c, client_data)) return(1); if (p == x) break; p--; } return(0); } else if (IS_CONCATENATION(x)) { register struct Concatenation * conc = &(((CordRep *)x) -> concatenation); register CORD left_part = conc -> left; register size_t left_len; left_len = LEFT_LEN(conc); if (i >= left_len) { if (CORD_riter4(conc -> right, i - left_len, f1, client_data)) { return(1); } return(CORD_riter4(left_part, left_len - 1, f1, client_data)); } else { return(CORD_riter4(left_part, i, f1, client_data)); } } else /* function */ { register struct Function * f = &(((CordRep *)x) -> function); register size_t j; for (j = i; ; j--) { if ((*f1)((*(f -> fn))(j, f -> client_data), client_data)) { return(1); } if (j == 0) return(0); } } }
/* Return 0 if past the end of cord, 1 o.w. */ void CORD__extend_path(register CORD_pos p) { register struct CORD_pe * current_pe = &(p[0].path[p[0].path_len]); register CORD top = current_pe -> pe_cord; register size_t pos = p[0].cur_pos; register size_t top_pos = current_pe -> pe_start_pos; register size_t top_len = GEN_LEN(top); /* Fill in the rest of the path. */ while(!CORD_IS_STRING(top) && IS_CONCATENATION(top)) { register struct Concatenation * conc = &(((CordRep *)top) -> concatenation); register size_t left_len; left_len = LEFT_LEN(conc); current_pe++; if (pos >= top_pos + left_len) { current_pe -> pe_cord = top = conc -> right; current_pe -> pe_start_pos = top_pos = top_pos + left_len; top_len -= left_len; } else { current_pe -> pe_cord = top = conc -> left; current_pe -> pe_start_pos = top_pos; top_len = left_len; } p[0].path_len++; } /* Fill in leaf description for fast access. */ if (CORD_IS_STRING(top)) { p[0].cur_leaf = top; p[0].cur_start = top_pos; p[0].cur_end = top_pos + top_len; } else { p[0].cur_end = 0; } if (pos >= top_pos + top_len) p[0].path_len = CORD_POS_INVALID; }
/* A version of CORD_substr that assumes i >= 0, n > 0, and i + n < length(x).*/ CORD CORD_substr_checked(CORD x, size_t i, size_t n) { if (CORD_IS_STRING(x)) { if (n > SUBSTR_LIMIT) { return(CORD_substr_closure(x, i, n, CORD_index_access_fn)); } else { char * result = (char *)GC_MALLOC_ATOMIC(n + 1); if (result == 0) OUT_OF_MEMORY; strncpy(result, x+i, n); result[n] = '\0'; return(result); } } else if (IS_CONCATENATION(x)) { struct Concatenation * conc = &(((CordRep *)x) -> concatenation); size_t left_len = LEFT_LEN(conc); size_t right_len = conc -> len - left_len; if (i >= left_len) { if (n == right_len) return(conc -> right); return(CORD_substr_checked(conc -> right, i - left_len, n)); } else if (i+n <= left_len) { if (n == left_len) return(conc -> left); return(CORD_substr_checked(conc -> left, i, n)); } else { /* Need at least one character from each side. */ CORD left_part; CORD right_part; size_t left_part_len = left_len - i; if (i == 0) { left_part = conc -> left; } else { left_part = CORD_substr_checked(conc -> left, i, left_part_len); } if (i + n == right_len + left_len) { right_part = conc -> right; } else { right_part = CORD_substr_checked(conc -> right, 0, n - left_part_len); } return(CORD_cat(left_part, right_part)); } } else /* function */ { if (n > SUBSTR_LIMIT) { if (IS_SUBSTR(x)) { /* Avoid nesting substring nodes. */ struct Function * f = &(((CordRep *)x) -> function); struct substr_args *descr = (struct substr_args *)(f -> client_data); return(CORD_substr_closure((CORD)descr->sa_cord, i + descr->sa_index, n, f -> fn)); } else { return(CORD_substr_closure(x, i, n, CORD_apply_access_fn)); } } else { char * result; struct Function * f = &(((CordRep *)x) -> function); char buf[SUBSTR_LIMIT+1]; char * p = buf; size_t j; size_t lim = i + n; for (j = i; j < lim; j++) { char c = (*(f -> fn))(j, f -> client_data); if (c == '\0') { return(CORD_substr_closure(x, i, n, CORD_apply_access_fn)); } *p++ = c; } result = (char *)GC_MALLOC_ATOMIC(n + 1); if (result == 0) OUT_OF_MEMORY; memcpy(result, buf, n); result[n] = '\0'; return(result); } } }