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

📄 sfmove.c

📁 su 的源代码库
💻 C
字号:
/* Copyright (c) Colorado School of Mines, 2006.*//* All rights reserved.                       */#include	"sfhdr.h"/*	Move data from one stream to another.**	This code is written so that it'll work even in the presence**	of stacking streams, pool, and discipline.**	If you must change it, be gentle.****	Written by Kiem-Phong Vo.*/#define MAX_SSIZE	((ssize_t)((~((size_t)0)) >> 1))#if __STD_CSfoff_t sfmove(Sfio_t* fr, Sfio_t* fw, Sfoff_t n, reg int rc)#elseSfoff_t sfmove(fr,fw,n,rc)Sfio_t*	fr;	/* moving data from this stream */Sfio_t*	fw;	/* moving data to this stream */Sfoff_t		n;	/* number of bytes/records to move. <0 for unbounded move */reg int		rc;	/* record separator */#endif{	reg uchar	*cp, *next;	reg ssize_t	r, w;	reg uchar	*endb;	reg int		direct;	Sfoff_t		n_move, sk, cur;	uchar		*rbuf = NIL(uchar*);	ssize_t		rsize = 0;	SFMTXSTART(fr, (Sfoff_t)0);	if(fw)		SFMTXLOCK(fw);	for(n_move = 0; n != 0; )	{		if(rc >= 0) /* moving records, let sfgetr() deal with record reading */		{	if(!(cp = (uchar*)sfgetr(fr,rc,0)) )				n = 0;			else			{	r = sfvalue(fr);				if(fw && (w = SFWRITE(fw, cp, r)) != r)				{	if(fr->extent >= 0 )						(void)SFSEEK(fr,(Sfoff_t)(-r),1);					if(fw->extent >= 0 && w > 0)						(void)SFSEEK(fw,(Sfoff_t)(-w),1);					n = 0;				}				else				{	n_move += 1;					if(n > 0)						n -= 1;				}			}			continue;		}		/* get the streams into the right mode */		if(fr->mode != SF_READ && _sfmode(fr,SF_READ,0) < 0)			goto done;		SFLOCK(fr,0);		/* flush the write buffer as necessary to make room */		if(fw)		{	if(fw->mode != SF_WRITE && _sfmode(fw,SF_WRITE,0) < 0 )				break;			SFLOCK(fw,0);			if(fw->next >= fw->endb ||			   (fw->next > fw->data && fr->extent < 0 &&			    (fw->extent < 0 || (fw->flags&SF_SHARE)) ) )				if(SFFLSBUF(fw,-1) < 0 )					break;		}		else if((cur = SFSEEK(fr, (Sfoff_t)0, SEEK_CUR)) >= 0 )		{	sk = n > 0 ? SFSEEK(fr, n, SEEK_CUR) : SFSEEK(fr, 0, SEEK_END);			if(sk > cur) /* safe to skip over data in current stream */			{	n_move += sk - cur;				if(n > 0)					n -= sk - cur;				continue;			}			/* else: stream unstacking may happen below */		}		/* about to move all, set map to a large amount */		if(n < 0 && (fr->bits&SF_MMAP) && !(fr->bits&SF_MVSIZE) )		{	SFMVSET(fr);			fr->bits |= SF_SEQUENTIAL; /* sequentially access data */		}		/* try reading a block of data */		direct = 0;		if((r = fr->endb - (next = fr->next)) <= 0)		{	/* amount of data remained to be read */			if((w = n > MAX_SSIZE ? MAX_SSIZE : (ssize_t)n) < 0)			{	if(fr->extent < 0)					w = fr->data == fr->tiny ? SF_GRAIN : fr->size;				else if((fr->extent-fr->here) > SF_NMAP*SF_PAGE)					w = SF_NMAP*SF_PAGE;				else	w = (ssize_t)(fr->extent-fr->here);			}			/* use a decent buffer for data transfer but make sure			   that if we overread, the left over can be retrieved			*/			if(!(fr->flags&SF_STRING) && !(fr->bits&SF_MMAP) &&			   (n < 0 || fr->extent >= 0) )			{	reg ssize_t maxw = 4*(_Sfpage > 0 ? _Sfpage : SF_PAGE);				/* direct transfer to a seekable write stream */				if(fw && fw->extent >= 0 && w <= (fw->endb-fw->next) )				{	w = fw->endb - (next = fw->next);					direct = SF_WRITE;				}				else if(w > fr->size && maxw > fr->size)				{	/* making our own buffer */					if(w >= maxw)						w = maxw;					else	w = ((w+fr->size-1)/fr->size)*fr->size;					if(rsize <= 0 && (rbuf = (uchar*)malloc(w)) )						rsize = w;					if(rbuf)					{	next = rbuf;						w = rsize;						direct = SF_STRING;					}				}			}			if(!direct)			{	/* make sure we don't read too far ahead */				if(n > 0 && fr->extent < 0 && (fr->flags&SF_SHARE) )				{	if((Sfoff_t)(r = fr->size) > n)						r = (ssize_t)n;				}				else	r = -1;				if((r = SFFILBUF(fr,r)) <= 0)					break;			done_filbuf:				next = fr->next;			}			else			{	/* actual amount to be read */				if(n > 0 && n < w)					w = (ssize_t)n;				if((r = SFRD(fr,next,w,fr->disc)) > 0)					fr->next = fr->endb = fr->endr = fr->data;				else if(r == 0)					break;		/* eof */				else	goto again;	/* popped stack */			}		}		/* compute the extent of data to be moved */		endb = next+r;		if(n > 0)		{	if(r > n)				r = (ssize_t)n;			n -= r;		}		n_move += r;		cp = next+r;		if(!direct)			fr->next += r;		else if((w = endb-cp) > 0)		{	/* move left-over to read stream */			if(w > fr->size)				w = fr->size;			memcpy((Void_t*)fr->data,(Void_t*)cp,w);			fr->endb = fr->data+w;			if((w = endb - (cp+w)) > 0)				(void)SFSK(fr,(Sfoff_t)(-w),SEEK_CUR,fr->disc);		}		if(fw)		{	if(direct == SF_WRITE)				fw->next += r;			else if(r <= (fw->endb-fw->next) )			{	memcpy((Void_t*)fw->next,(Void_t*)next,r);				fw->next += r;			}			else if((w = SFWRITE(fw,(Void_t*)next,r)) != r)			{	/* a write error happened */				if(w > 0)				{	r -= w;					n_move -= r;				}				if(fr->extent >= 0)					(void)SFSEEK(fr,(Sfoff_t)(-r),1);				break;			}		}	again:		SFOPEN(fr,0);		if(fw)			SFOPEN(fw,0);	}done:	if(n < 0 && (fr->bits&SF_MMAP) && (fr->bits&SF_MVSIZE))	{	/* back to normal access mode */		SFMVUNSET(fr);		if((fr->bits&SF_SEQUENTIAL) && (fr->data))			SFMMSEQOFF(fr,fr->data,fr->endb-fr->data);		fr->bits &= ~SF_SEQUENTIAL;	}	if(rbuf)		free(rbuf);	SFOPEN(fr,0);	if(fw)	{	SFOPEN(fw,0);		SFMTXUNLOCK(fw);	}	SFMTXRETURN(fr, n_move);}

⌨️ 快捷键说明

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