⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cordbscs.c

📁 A garbage collector for C and C
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 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);    }}			#undef CORD_iterint CORD_iter(CORD x, CORD_iter_fn f1, void * client_data){    return(CORD_iter5(x, 0, f1, CORD_NO_FN, client_data));}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);        }    }}int CORD_riter(CORD x, CORD_iter_fn f1, void * client_data){    return(CORD_riter4(x, CORD_len(x) - 1, f1, client_data));}/* * The following functions are concerned with balancing cords. * Strategy: * Scan the cord from left to right, keeping the cord scanned so far * as a forest of balanced trees of exponentialy decreasing length. * When a new subtree needs to be added to the forest, we concatenate all * shorter ones to the new tree in the appropriate order, and then insert * the result into the forest. * Crucial invariants: * 1. The concatenation of the forest (in decreasing order) with the *     unscanned part of the rope is equal to the rope being balanced. * 2. All trees in the forest are balanced. * 3. forest[i] has depth at most i. */typedef struct {    CORD c;    size_t len;		/* Actual length of c 	*/} ForestElement;static size_t min_len [ MAX_DEPTH ];static int min_len_init = 0;int CORD_max_len;typedef ForestElement Forest [ MAX_DEPTH ];			/* forest[i].len >= fib(i+1)	        */			/* The string is the concatenation	*/			/* of the forest in order of DECREASING */			/* indices.				*/void CORD_init_min_len(){    register int i;    register size_t last, previous, current;            min_len[0] = previous = 1;    min_len[1] = last = 2;    for (i = 2; i < MAX_DEPTH; i++) {    	current = last + previous;    	if (current < last) /* overflow */ current = last;    	min_len[i] = current;    	previous = last;    	last = current;    }    CORD_max_len = last - 1;    min_len_init = 1;}void CORD_init_forest(ForestElement * forest, size_t max_len){    register int i;        for (i = 0; i < MAX_DEPTH; i++) {    	forest[i].c = 0;    	if (min_len[i] > max_len) return;    }    ABORT("Cord too long");}/* Add a leaf to the appropriate level in the forest, cleaning		*//* out lower levels as necessary.					*//* Also works if x is a balanced tree of concatenations; however	*//* in this case an extra concatenation node may be inserted above x;	*//* This node should not be counted in the statement of the invariants.	*/void CORD_add_forest(ForestElement * forest, CORD x, size_t len){    register int i = 0;    register CORD sum = CORD_EMPTY;    register size_t sum_len = 0;        while (len > min_len[i + 1]) {    	if (forest[i].c != 0) {    	    sum = CORD_cat(forest[i].c, sum);    	    sum_len += forest[i].len;    	    forest[i].c = 0;    	}        i++;    }    /* Sum has depth at most 1 greter than what would be required 	*/    /* for balance.							*/    sum = CORD_cat(sum, x);    sum_len += len;    /* If x was a leaf, then sum is now balanced.  To see this		*/    /* consider the two cases in which forest[i-1] either is or is 	*/    /* not empty.							*/    while (sum_len >= min_len[i]) {    	if (forest[i].c != 0) {    	    sum = CORD_cat(forest[i].c, sum);    	    sum_len += forest[i].len;    	    /* This is again balanced, since sum was balanced, and has	*/    	    /* allowable depth that differs from i by at most 1.	*/    	    forest[i].c = 0;    	}        i++;    }    i--;    forest[i].c = sum;    forest[i].len = sum_len;}CORD CORD_concat_forest(ForestElement * forest, size_t expected_len){    register int i = 0;    CORD sum = 0;    size_t sum_len = 0;        while (sum_len != expected_len) {    	if (forest[i].c != 0) {    	    sum = CORD_cat(forest[i].c, sum);    	    sum_len += forest[i].len;    	}        i++;    }    return(sum);}/* Insert the frontier of x into forest.  Balanced subtrees are	*//* treated as leaves.  This potentially adds one to the depth	*//* of the final tree.						*/void CORD_balance_insert(CORD x, size_t len, ForestElement * forest){    register 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])) {    	register 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);    }}CORD CORD_balance(CORD x){    Forest forest;    register size_t len;        if (x == 0) return(0);    if (CORD_IS_STRING(x)) return(x);    if (!min_len_init) CORD_init_min_len();    len = LEN(x);    CORD_init_forest(forest, len);    CORD_balance_insert(x, len, forest);    return(CORD_concat_forest(forest, len));}/* Position primitives	*//* Private routines to deal with the hard cases only: *//* P contains a prefix of the  path to cur_pos.	Extend it to a full	*//* path and set up leaf info.						*//* 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;}char CORD__pos_fetch(register CORD_pos p){    /* Leaf is a function node */    struct CORD_pe * pe = &((p)[0].path[(p)[0].path_len]);    CORD leaf = pe -> pe_cord;    register struct Function * f = &(((CordRep *)leaf) -> function);        if (!IS_FUNCTION(leaf)) ABORT("CORD_pos_fetch: bad leaf");    return ((*(f -> fn))(p[0].cur_pos - pe -> pe_start_pos, f -> client_data));}void CORD__next(register CORD_pos p){    register size_t cur_pos = p[0].cur_pos + 1;    register struct CORD_pe * current_pe = &((p)[0].path[(p)[0].path_len]);    register CORD 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	*/    	register struct Function * f = &(((CordRep *)leaf) -> function);    	register size_t start_pos = current_pe -> pe_start_pos;    	register size_t end_pos = start_pos + f -> len;    	    	if (cur_pos < end_pos) {    	  /* Fill cache and return. */    	    register size_t i;    	    register size_t limit = cur_pos + FUNCTION_BUF_SZ;    	    register CORD_fn fn = f -> fn;    	    register 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);}void CORD__prev(register CORD_pos p){    register struct CORD_pe * pe = &(p[0].path[p[0].path_len]);        if (p[0].cur_pos == 0) {        p[0].path_len = CORD_POS_INVALID;        return;    }    p[0].cur_pos--;    if (p[0].cur_pos >= pe -> pe_start_pos) return;        /* Beginning of leaf	*/        /* Pop the stack until we find two concatenation nodes with the 	*/    /* different start position: this implies we were in right part.	*/    {    	register struct CORD_pe * current_pe = &((p)[0].path[(p)[0].path_len]);    	    	while (p[0].path_len > 0    	       && current_pe[0].pe_start_pos == current_pe[-1].pe_start_pos) {    	    p[0].path_len--;    	    current_pe--;    	}    }    p[0].path_len--;    CORD__extend_path(p);}#undef CORD_pos_fetch#undef CORD_next#undef CORD_prev#undef CORD_pos_to_index#undef CORD_pos_to_cord#undef CORD_pos_validchar CORD_pos_fetch(register CORD_pos p){    if (p[0].cur_start <= p[0].cur_pos && p[0].cur_pos < p[0].cur_end) {    	return(p[0].cur_leaf[p[0].cur_pos - p[0].cur_start]);    } else {        return(CORD__pos_fetch(p));    }}void CORD_next(CORD_pos p){    if (p[0].cur_pos < p[0].cur_end - 1) {    	p[0].cur_pos++;    } else {    	CORD__next(p);    }}void CORD_prev(CORD_pos p){    if (p[0].cur_end != 0 && p[0].cur_pos > p[0].cur_start) {    	p[0].cur_pos--;    } else {    	CORD__prev(p);    }}size_t CORD_pos_to_index(CORD_pos p){    return(p[0].cur_pos);}CORD CORD_pos_to_cord(CORD_pos p){    return(p[0].path[0].pe_cord);}int CORD_pos_valid(CORD_pos p){    return(p[0].path_len != CORD_POS_INVALID);}void CORD_set_pos(CORD_pos p, CORD x, size_t i){    if (x == CORD_EMPTY) {    	p[0].path_len = CORD_POS_INVALID;    	return;    }    p[0].path[0].pe_cord = x;    p[0].path[0].pe_start_pos = 0;    p[0].path_len = 0;    p[0].cur_pos = i;    CORD__extend_path(p);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -