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

📄 ps_impl.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	pieces = PIECES_IN_TABLE(private);	if (private->length == 0) {	    /* Special case occurring after everything replaced by nothing. */	    ASSUME(pieces[0].pos == ES_INFINITY);	    if (count == 0) {		/* Nothing replaced by nothing => leave well enough alone! */		return(private->position);	    }	    pieces[current = 0].pos = 0;	    goto Append_Only;	}	delta = get_current_offset(private);	current = private->current;	if (last_plus_one > private->position) {	    /* Replace a NON-empty region */	    if (delta != 0) {		/* Split the current piece at the insert point. */		pieces = split_piece(&private->pieces, current, delta);		current++;	    }	    if (last_plus_one > PS_LAST_PLUS_ONE(pieces[current])) {		/* Replace region spanning multiple pieces */		end_index =		    ft_bounding_index(&private->pieces, last_plus_one-1);		    /* -1 ensures that pieces[end_index] < last_plus_one,		     *   preventing creation of a 0-length piece below.		     */		ASSERT(VALID_PIECE_INDEX(private, end_index));	    } else {		/* Replace region within a single piece */		end_index = current;	    }	    if (last_plus_one < PS_LAST_PLUS_ONE(pieces[end_index])) {		/* Split the end piece at the last_plus_one point */		pieces = split_piece(&private->pieces, end_index,				     last_plus_one-pieces[end_index].pos);	    }	    /* Replace region now exactly equals [current..end_index] pieces.	     * Make sure all es_replace(scratch, ...) succeed before	     * modifying private->... (including pieces) any further.	     */	    new_rec_insert =		write_header_etc(scratch, private, last_plus_one,				 (long)count, buf, count_used,				 &es_temp, &delete_pieces_length,				 current, end_index+1);	    if (new_rec_insert == ES_CANNOT_SET) {		goto Error_Return;	    }	    if (count == 0) {		current--;	/* Make ft_shift_out & ft_add_delta work */	    }	    /* Recycle current piece, so don't shift it out */	    ft_shift_out(&private->pieces, current+1, end_index+1);	    /* Meaning 2: total change to length */	    delta = count - delete_pieces_length;	} else if (count == 0) {	    /* Empty region replaced by nothing => leave well enough alone!	     * Not catching this case creates an extra 0-length piece.	     */	    return(private->position);	} else {	    /* Replace an empty region */	    int	at_end_of_stream = PS_IS_AT_END(private, delta, current);	    if (private->position == private->last_write_plus_one) {		es_temp = es_replace(scratch, ES_INFINITY,				     count, buf, count_used);		if (es_temp == ES_CANNOT_SET) {		    goto Error_Return;		}		ASSUME(count == *count_used);		if (private->rec_insert_len == 0) {		    /* Last replace was a delete, so no scratch piece exists */		    /* Split the current piece at the insert point */		    pieces = split_piece(&private->pieces, current, delta);		    if (delta != 0) {			ASSUME(at_end_of_stream);			current++;			delta = 0;		    }		    PS_SET_SCRATCH_SANDP(pieces[current],					private->rec_insert+sizeof(long_temp));		} else if (at_end_of_stream) {		    /* Last replace was at end of stream => don't back up */		} else {		    ASSERT(delta == 0 && current > 0);		    current--;		    delta = private->position - pieces[current].pos;		}		ASSERT(delta == pieces[current].length);		delta = count;	    /* Meaning 2: total change to length */		private->rec_insert_len += delta;		pieces[current].length += delta;		/* Correct the insert length (this is very inefficient) */		long_temp = private->rec_insert_len;		es_temp = es_set_position(scratch, private->rec_insert);		ASSERT(es_temp == private->rec_insert);		es_temp = es_replace(scratch,				private->rec_insert+sizeof(long_temp),				sizeof(long_temp), (char *)&long_temp,				&replace_used);	    } else {		if (delta != 0) {		    /* Split the current piece at the insert point */		    pieces = split_piece(&private->pieces, current, delta);		    current++;		    if (at_end_of_stream) {			/* Append at the very end of the stream will create			 *   a zero length piece which is unnecessary, so we			 *   detect this case and recycle the piece.			 */			goto Append_Only;		    }		}		/* Handle the delta == 0 case.  Create new piece */		pieces = split_piece(&private->pieces, current, 0L);Append_Only:		/* Make sure all es_replace(scratch, ...) succeed before		 * modifying private->... (including pieces) any further.		 */		new_rec_insert =		    write_header_etc(scratch, private, last_plus_one, count,				     buf, count_used, &es_temp, (int *)0,				     -1, -1);		if (new_rec_insert == ES_CANNOT_SET) {		    /* Reverse all damaging changes to pieces */		    if (private->length == 0) {			pieces[0].pos = ES_INFINITY;		    } else if (pieces[current].length == 0) {			ft_shift_out(&private->pieces, current, current+1);		    }		    goto Error_Return;		}		delta = count;	    /* Meaning 2: total change to length */	    }	}	/* Update (if necessary) the fields tracking the insert record.	 * Also fix up the associated piece fields.         */	if (new_rec_insert != ES_INFINITY) {	    private->rec_insert = new_rec_insert;	    private->rec_insert_len = count;	    private->rec_start = scratch_length;	    if (private->oldest_not_undone_mark == ES_INFINITY)		private->oldest_not_undone_mark = scratch_length;	    ASSUME(count == *count_used);	    if (count != 0) {		pieces[current].length = count;		ASSERT(es_temp == private->rec_insert+sizeof(long_temp));		PS_SET_SCRATCH_SANDP(pieces[current], es_temp);	    }	}	/* Adjust position, etc. to reflect the overall replace */	ft_add_delta(private->pieces, current+1, delta);	private->length += delta;	SET_POSITION(private, private->position + count);	private->last_write_plus_one = private->position;	ASSUME(0 <= private->position && private->position <= MAX_LENGTH);	ASSUME(ps_pieces_are_consistent(private));	return(private->position);Error_Return:	private->status = (Es_status)es_get(scratch, ES_STATUS);	/* Copy scratch status first in case attempt to "back out"	 * failed es_replace's modify the status.	 */	(void) es_set_position(scratch, scratch_length);	(void) es_replace(scratch, ES_INFINITY, 0, NULL, count_used);	INVALIDATE_CURRENT(private);	ASSUME(ps_pieces_are_consistent(private));	return(ES_CANNOT_SET);}static Es_indexwrite_record_header(esh, private, last_plus_one, dp_count)	Es_handle		esh;	register Piece_table	private;	Es_index		last_plus_one;	int			dp_count;{	struct piece_record_header	r_header;	register Es_index		result;	int				replace_used;	r_header.pos_prev_rec = private->rec_start;	r_header.flags = 0;	r_header.start = private->position;	r_header.stop_plus_one = last_plus_one;	r_header.dp_count = dp_count;	result = es_replace(esh, ES_INFINITY,			    sizeof(r_header), (char *)&r_header,			    &replace_used);	return(result);}static intrecord_deleted_pieces(esh, private, pieces, first, last_plus_one, next)	Es_handle	 esh;	Piece_table	 private;	Piece		 pieces;	int		 first, last_plus_one;	Es_index	*next;{	struct deleted_piece	d_header;	int			dummy;	register Piece		current, stop_plus_one;	register int		result = 0;	register Es_index	replace_result;	stop_plus_one = &pieces[last_plus_one];	for (current = &pieces[first]; current < stop_plus_one; current++) {	    d_header.source_and_pos = current->source_and_pos;	    result += (d_header.length = current->length);	    replace_result =		es_replace(esh, ES_INFINITY,			   sizeof(d_header), (char *)&d_header, &dummy);	    if (replace_result == ES_CANNOT_SET)		break;	}	*next = replace_result;	return(result);}/* Returns the new value for private->rec_insert */static Es_indexwrite_header_etc(esh, private, last_plus_one, count, buf, count_used,		 contents_start,		 deleted_pieces_length, first_deleted, last_plus_one_deleted)	register Es_handle	 esh;	register Piece_table	 private;	Es_index		 last_plus_one;	long int		 count;	long int		*count_used;	char			*buf;	Es_index		*contents_start;	int			*deleted_pieces_length;	int			 first_deleted, last_plus_one_deleted;{	register Es_index	 result;	Es_index		 es_temp;	int			 replace_used;	/* Write the record header (and possibly) deleted pieces. */	result = write_record_header(esh, private, last_plus_one,				     last_plus_one_deleted-first_deleted);	if (result == ES_CANNOT_SET)	    return(ES_CANNOT_SET);	if (first_deleted < last_plus_one_deleted) {	    *deleted_pieces_length =		record_deleted_pieces(esh, private, PIECES_IN_TABLE(private),				      first_deleted, last_plus_one_deleted,				      &es_temp);	    if (es_temp == ES_CANNOT_SET)		return(ES_CANNOT_SET);	    result = es_temp;	}	*contents_start =	    es_replace(esh, ES_INFINITY, sizeof(count),			(char *)&count, &replace_used);	if (*contents_start == ES_CANNOT_SET)	    return(ES_CANNOT_SET);	/* Do the insert */	if (count != 0) {	    es_temp = es_replace(esh, ES_INFINITY, count, buf, count_used);	    if (es_temp == ES_CANNOT_SET)		return(ES_CANNOT_SET);	}	return(result);}static Es_handleps_pieces_for_span(esh, first, last_plus_one, to_recycle)	Es_handle	esh;	Es_index	first, last_plus_one;	Es_handle	to_recycle;{	register Piece_table	private = ABS_TO_REP(esh);	register Piece		result_pieces;	register int		is_scratch;	register Es_index	delta, source_pos;	int			first_index, last_index;	Es_handle		result = (Es_handle)0;	Piece_table		r_private;	if (last_plus_one > private->length)	    last_plus_one = private->length;	if (first >= last_plus_one) {	    goto Bad_Args;	}	ASSUME(allock());	first_index = ft_bounding_index(&private->pieces, first);	last_index = ft_bounding_index(&private->pieces, last_plus_one-1);	if (to_recycle) {	    result = to_recycle;	    r_private = ABS_TO_REP(result);	    ASSUME(r_private->magic == PS_MAGIC && r_private->parent == esh);	    if (r_private->pieces.last_plus_one <= (last_index-first_index)) {		ft_destroy(&r_private->pieces);	  /* Zeros .last_plus_one */	    }	} else {	    result = ps_NEW(0);	    if (result == (Es_handle)0)		goto Out_Of_Memory;	    r_private = ABS_TO_REP(result);	    r_private->parent = esh;	    r_private->original = private->original;	    r_private->scratch = private->scratch;	    r_private->last_write_plus_one = r_private->rec_insert =		r_private->rec_start = ES_CANNOT_SET;	    r_private->rec_insert_len = -1;	}	if (r_private->pieces.last_plus_one == 0) {	    r_private->pieces =		FT_CLIENT_CREATE(last_index-first_index+1, Piece_object);	    if (r_private->pieces.seq == (Es_index *)0)		goto Out_Of_Memory;	}	FT_CLEAR_ALL(r_private->pieces);	copy_pieces(&r_private->pieces, 0, &private->pieces,		    first_index, last_index+1);	/*	 * Fix up the end pieces.	 */	result_pieces = &PIECES_IN_TABLE(r_private)[last_index-first_index];	result_pieces->length = last_plus_one - result_pieces->pos;	result_pieces = &PIECES_IN_TABLE(r_private)[0];	delta = first - result_pieces->pos;	if (delta != 0) {	    result_pieces->pos = first;	    is_scratch = PS_SANDP_SOURCE(*result_pieces);	    source_pos = PS_SANDP_POS(*result_pieces);	    source_pos += delta;	    result_pieces->length -= delta;	    PS_SET_SANDP(*result_pieces, source_pos, is_scratch);	}	SET_POSITION(r_private, first);	r_private->length = last_plus_one;	ASSUME(allock());	return(result);Out_Of_Memory:	if (result) {	    es_destroy(result);	    result = (Es_handle)0;	}Bad_Args:	if (to_recycle)	    es_destroy(to_recycle);	return(result);}staticcopy_pieces(to_table, to_index, from_table, first, last_plus_one)	register ft_handle	to_table, from_table;	int			to_index, first, last_plus_one;{	register int		sizeof_element = from_table->sizeof_element;	ASSERT(to_table->sizeof_element == sizeof_element);	bcopy((char *)from_table->seq + first*sizeof_element,	      (char *)to_table->seq + to_index*sizeof_element,	      (last_plus_one-first)*sizeof_element);}static intget_current_offset(private)	register Piece_table	 private;{	register Piece		 current;	register int		 result;	if (private->current == CURRENT_NULL)	    private->current =		ft_bounding_index(&private->pieces, private->position);	ASSERT(VALID_PIECE_INDEX(private, private->current));	current = &PIECES_IN_TABLE(private)[private->current];	result = private->position - current->pos;	ASSUME(result < current->length ||		PS_IS_AT_END(private, result, private->current) );	return(result);}static voidps_insert_pieces(esh, to_insert)	Es_handle	esh, to_insert;/* * Much of this routine is stolen from ps_replace. * A special convention established by this routine is that if the scratch *   stream has a replace record with start == stop_plus_one and a non-zero *   deleted piece count, then it is a result of inserting pieces, rather than *   characters. */{	ft_handle		rep = (ft_handle)					&(ABS_TO_REP(to_insert))->pieces;	long int		long_temp;	int			at_end_of_stream, replace_used;	long int		delta;	int			save_last_plus_one;	Es_index		scratch_length, es_temp;	register Piece		pieces;	register int		current, last_valid;	register Piece_table	private = ABS_TO_REP(esh);	register Es_handle	scratch = private->scratch;	ASSERT(rep != FT_NULL);	last_valid = ft_bounding_index(rep, ES_INFINITY-1);	ASSERT(last_valid != rep->last_plus_one);	/* Prepare the insertion area. */	pieces = PIECES_IN_TABLE(private);	if (private->length == 0 && pieces[0].pos == ES_INFINITY) {	    /* Special case that occurs if replaced everything by nothing. */	    current = 0;	    delta = 0;	    at_end_of_stream = 1;	    pieces[0].pos = 0;	    pieces[0].length = 0;	    PS_SET_SCRATCH_SANDP(pieces[0], 0);

⌨️ 快捷键说明

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