?? cordxtra.c
字號(hào):
{ register chr_data * d = (chr_data *)client_data; register char * occ = strchr(s, d -> target); if (occ == 0) { d -> pos += strlen(s); return(0); } else { d -> pos += occ - s; return(1); }}size_t CORD_chr(CORD x, size_t i, int c){ chr_data d; d.pos = i; d.target = c; if (CORD_iter5(x, i, CORD_chr_proc, CORD_batched_chr_proc, &d)) { return(d.pos); } else { return(CORD_NOT_FOUND); }}size_t CORD_rchr(CORD x, size_t i, int c){ chr_data d; d.pos = i; d.target = c; if (CORD_riter4(x, i, CORD_rchr_proc, &d)) { return(d.pos); } else { return(CORD_NOT_FOUND); }}/* Find the first occurrence of s in x at position start or later. *//* This uses an asymptotically poor algorithm, which should typically *//* perform acceptably. We compare the first few characters directly, *//* and call CORD_ncmp whenever there is a partial match. *//* This has the advantage that we allocate very little, or not at all. *//* 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); }}void CORD_ec_flush_buf(CORD_ec x){ register size_t len = x[0].ec_bufptr - x[0].ec_buf; char * s; if (len == 0) return; s = GC_MALLOC_ATOMIC(len+1); memcpy(s, x[0].ec_buf, len); s[len] = '\0'; x[0].ec_cord = CORD_cat_char_star(x[0].ec_cord, s, len); x[0].ec_bufptr = x[0].ec_buf;}void CORD_ec_append_cord(CORD_ec x, CORD s){ CORD_ec_flush_buf(x); x[0].ec_cord = CORD_cat(x[0].ec_cord, s);}/*ARGSUSED*/char CORD_nul_func(size_t i, void * client_data){ return((char)(unsigned long)client_data);}CORD CORD_chars(char c, size_t i){ return(CORD_from_fn(CORD_nul_func, (void *)(unsigned long)c, i));}CORD CORD_from_file_eager(FILE * f){ register int c; CORD_ec ecord; CORD_ec_init(ecord); for(;;) { c = getc(f); if (c == 0) { /* Append the right number of NULs */ /* Note that any string of NULs is rpresented in 4 words, */ /* independent of its length. */ register size_t count = 1; CORD_ec_flush_buf(ecord); while ((c = getc(f)) == 0) count++; ecord[0].ec_cord = CORD_cat(ecord[0].ec_cord, CORD_nul(count)); } if (c == EOF) break; CORD_ec_append(ecord, c); } (void) fclose(f); return(CORD_balance(CORD_ec_to_cord(ecord)));}/* The state maintained for a lazily read file consists primarily *//* of a large direct-mapped cache of previously read values. *//* We could rely more on stdio buffering. That would have 2 *//* disadvantages: *//* 1) Empirically, not all fseek implementations preserve the *//* buffer whenever they could. *//* 2) It would fail if 2 different sections of a long cord *//* were being read alternately. *//* We do use the stdio buffer for read ahead. *//* To guarantee thread safety in the presence of atomic pointer *//* writes, cache lines are always replaced, and never modified in *//* place. */# define LOG_CACHE_SZ 14# define CACHE_SZ (1 << LOG_CACHE_SZ)# define LOG_LINE_SZ 9# define LINE_SZ (1 << LOG_LINE_SZ)typedef struct { size_t tag; char data[LINE_SZ]; /* data[i%LINE_SZ] = ith char in file if tag = i/LINE_SZ */} cache_line;typedef struct { FILE * lf_file; size_t lf_current; /* Current file pointer value */ cache_line * volatile lf_cache[CACHE_SZ/LINE_SZ];} lf_state;# define MOD_CACHE_SZ(n) ((n) & (CACHE_SZ - 1))# define DIV_CACHE_SZ(n) ((n) >> LOG_CACHE_SZ)# define MOD_LINE_SZ(n) ((n) & (LINE_SZ - 1))# define DIV_LINE_SZ(n) ((n) >> LOG_LINE_SZ)# define LINE_START(n) ((n) & ~(LINE_SZ - 1))typedef struct { lf_state * state; size_t file_pos; /* Position of needed character. */ cache_line * new_cache;} refill_data;/* Executed with allocation lock. */static char refill_cache(client_data)refill_data * client_data;{ register lf_state * state = client_data -> state; register size_t file_pos = client_data -> file_pos; FILE *f = state -> lf_file; size_t line_start = LINE_START(file_pos); size_t line_no = DIV_LINE_SZ(MOD_CACHE_SZ(file_pos)); cache_line * new_cache = client_data -> new_cache; if (line_start != state -> lf_current && fseek(f, line_start, SEEK_SET) != 0) { ABORT("fseek failed"); } if (fread(new_cache -> data, sizeof(char), LINE_SZ, f) <= file_pos - line_start) { ABORT("fread failed"); } new_cache -> tag = DIV_LINE_SZ(file_pos); /* Store barrier goes here. */ ATOMIC_WRITE(state -> lf_cache[line_no], new_cache); state -> lf_current = line_start + LINE_SZ; return(new_cache->data[MOD_LINE_SZ(file_pos)]);}char CORD_lf_func(size_t i, void * client_data){ register lf_state * state = (lf_state *)client_data; register cache_line * volatile * cl_addr = &(state -> lf_cache[DIV_LINE_SZ(MOD_CACHE_SZ(i))]); register cache_line * cl = (cache_line *)ATOMIC_READ(cl_addr); if (cl == 0 || cl -> tag != DIV_LINE_SZ(i)) { /* Cache miss */ refill_data rd; rd.state = state; rd.file_pos = i; rd.new_cache = GC_NEW_ATOMIC(cache_line); if (rd.new_cache == 0) OUT_OF_MEMORY; return((char)(GC_word) GC_call_with_alloc_lock((GC_fn_type) refill_cache, &rd)); } return(cl -> data[MOD_LINE_SZ(i)]);} /*ARGSUSED*/void CORD_lf_close_proc(void * obj, void * client_data) { if (fclose(((lf_state *)obj) -> lf_file) != 0) { ABORT("CORD_lf_close_proc: fclose failed"); }} CORD CORD_from_file_lazy_inner(FILE * f, size_t len){ register lf_state * state = GC_NEW(lf_state); register int i; if (state == 0) OUT_OF_MEMORY; if (len != 0) { /* Dummy read to force buffer allocation. */ /* This greatly increases the probability */ /* of avoiding deadlock if buffer allocation */ /* is redirected to GC_malloc and the */ /* world is multithreaded. */ char buf[1]; (void) fread(buf, 1, 1, f); rewind(f); } state -> lf_file = f; for (i = 0; i < CACHE_SZ/LINE_SZ; i++) { state -> lf_cache[i] = 0; } state -> lf_current = 0; GC_REGISTER_FINALIZER(state, CORD_lf_close_proc, 0, 0, 0); return(CORD_from_fn(CORD_lf_func, state, len));}CORD CORD_from_file_lazy(FILE * f){ register long len; if (fseek(f, 0l, SEEK_END) != 0) { ABORT("Bad fd argument - fseek failed"); } if ((len = ftell(f)) < 0) { ABORT("Bad fd argument - ftell failed"); } rewind(f); return(CORD_from_file_lazy_inner(f, (size_t)len));}# define LAZY_THRESHOLD (128*1024 + 1)CORD CORD_from_file(FILE * f){ register long len; if (fseek(f, 0l, SEEK_END) != 0) { ABORT("Bad fd argument - fseek failed"); } if ((len = ftell(f)) < 0) { ABORT("Bad fd argument - ftell failed"); } rewind(f); if (len < LAZY_THRESHOLD) { return(CORD_from_file_eager(f)); } else { return(CORD_from_file_lazy_inner(f, (size_t)len)); }}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -