3
/* Reserve a segment of data or buffer.
5
** Written by Kiem-Phong Vo.
9
Void_t* sfreserve(reg Sfio_t* f, ssize_t size, int type)
11
Void_t* sfreserve(f,size,type)
12
reg Sfio_t* f; /* file to peek */
13
ssize_t size; /* size of peek */
14
int type; /* LOCKR: lock stream, LASTR: last record */
22
SFMTXSTART(f,NIL(Void_t*));
24
/* initialize io states */
25
rsrv = NIL(Sfrsrv_t*);
28
/* return the last record */
30
{ if((rsrv = f->rsrv) && (n = -rsrv->slen) > 0)
33
SFMTXRETURN(f, (Void_t*)rsrv->data);
35
else SFMTXRETURN(f, NIL(Void_t*));
38
if(type > 0 && !(type == SF_LOCKR || type == 1) )
39
SFMTXRETURN(f, NIL(Void_t*));
41
if((sz = size) == 0 && type != 0)
42
{ /* only return the current status and possibly lock stream */
43
if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0)
44
SFMTXRETURN(f, NIL(Void_t*));
47
if((n = f->endb - f->next) < 0)
50
if(!f->data && type > 0)
58
/* iterate until get to a stream that has data or buffer space */
60
{ /* prefer read mode so that data is always valid */
61
if(!(mode = (f->flags&SF_READ)) )
63
if((int)f->mode != mode && _sfmode(f,mode,0) < 0)
70
if((n = f->endb - f->next) < 0) /* possible for string+rw */
73
if(n > 0 && n >= sz) /* all done */
76
/* do a buffer refill or flush */
78
(void)SFFLSBUF(f, -1);
79
else if(type > 0 && f->extent < 0 && (f->flags&SF_SHARE) )
80
{ if(n == 0) /* peek-read only if there is no buffered data */
82
(void)SFFILBUF(f, sz == 0 ? -1 : (sz-n) );
84
if((n = f->endb - f->next) < sz)
86
{ f->endb = f->endr = f->next;
92
else (void)SFFILBUF(f, sz == 0 ? -1 : (sz-n) );
95
if((n = f->endb - f->next) > 0)
100
/* this test fails only if unstacked to an opposite stream */
101
if((f->mode&mode) != 0)
105
if(n > 0 && n < sz && (f->mode&mode) != 0 )
106
{ /* try to accomodate request size */
107
if(f->flags&SF_STRING)
108
{ if((f->mode&SF_WRITE) && (f->flags&SF_MALLOC) )
109
{ (void)SFWR(f,f->next,sz,f->disc);
110
n = f->endb - f->next;
113
else if(f->mode&SF_WRITE)
114
{ if(type > 0 && (rsrv = _sfrsrv(f,sz)) )
117
else /*if(f->mode&SF_READ)*/
118
{ if(type <= 0 && (rsrv = _sfrsrv(f,sz)) &&
119
(n = SFREAD(f,(Void_t*)rsrv->data,sz)) < sz)
125
/* return true buffer size */
130
if((sz > 0 && n < sz) || (n == 0 && type <= 0) )
131
SFMTXRETURN(f, NIL(Void_t*));
133
if((data = rsrv ? (Void_t*)rsrv->data : (Void_t*)f->next) )
135
{ f->mode |= SF_PEEK;
136
f->endr = f->endw = f->data;
138
else if(data == (Void_t*)f->next)
139
f->next += (size >= 0 ? size : n);
142
SFMTXRETURN(f, data);