Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/sfio/sffilbuf.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1985-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#include "sfhdr.h"
23
24
/* Fill the buffer of a stream with data.
25
** If n < 0, sffilbuf() attempts to fill the buffer if it's empty.
26
** If n == 0, if the buffer is not empty, just return the first byte;
27
** otherwise fill the buffer and return the first byte.
28
** If n > 0, even if the buffer is not empty, try a read to get as
29
** close to n as possible. n is reset to -1 if stack pops.
30
**
31
** Written by Kiem-Phong Vo
32
*/
33
34
#if __STD_C
35
int _sffilbuf(Sfio_t* f, reg int n)
36
#else
37
int _sffilbuf(f,n)
38
Sfio_t* f; /* fill the read buffer of this stream */
39
reg int n; /* see above */
40
#endif
41
{
42
reg ssize_t r;
43
reg int first, local, rcrv, rc, justseek;
44
SFMTXDECL(f); /* declare a local stream variable for multithreading */
45
46
SFMTXENTER(f,-1);
47
48
GETLOCAL(f,local);
49
50
/* any peek data must be preserved across stacked streams */
51
rcrv = f->mode&(SF_RC|SF_RV|SF_LOCK);
52
rc = f->getr;
53
54
justseek = f->bits&SF_JUSTSEEK; f->bits &= ~SF_JUSTSEEK;
55
56
for(first = 1;; first = 0, (f->mode &= ~SF_LOCK) )
57
{ /* check mode */
58
if(SFMODE(f,local) != SF_READ && _sfmode(f,SF_READ,local) < 0)
59
SFMTXRETURN(f,-1);
60
SFLOCK(f,local);
61
62
/* current extent of available data */
63
if((r = f->endb-f->next) > 0)
64
{ /* on first iteration, n is amount beyond current buffer;
65
afterward, n is the exact amount requested */
66
if((first && n <= 0) || (!first && n <= r) ||
67
(f->flags&SF_STRING))
68
break;
69
70
/* try shifting left to make room for new data */
71
if(!(f->bits&SF_MMAP) && f->next > f->data &&
72
n > (f->size - (f->endb-f->data)) )
73
{ ssize_t s = r;
74
75
/* try to maintain block alignment */
76
if(f->blksz > 0 && (f->here%f->blksz) == 0 )
77
{ s = ((r + f->blksz-1)/f->blksz)*f->blksz;
78
if(s+n > f->size)
79
s = r;
80
}
81
82
memmove(f->data, f->endb-s, s);
83
f->next = f->data + (s-r);
84
f->endb = f->data + s;
85
}
86
}
87
else if(!(f->flags&SF_STRING) && !(f->bits&SF_MMAP) )
88
f->next = f->endb = f->endr = f->data;
89
90
if(f->bits&SF_MMAP)
91
r = n > 0 ? n : f->size;
92
else if(!(f->flags&SF_STRING) )
93
{ r = f->size - (f->endb - f->data); /* available buffer */
94
if(n > 0)
95
{ if(r > n && f->extent < 0 && (f->flags&SF_SHARE) )
96
r = n; /* read only as much as requested */
97
else if(justseek && n <= f->iosz && f->iosz <= f->size)
98
r = f->iosz; /* limit buffer filling */
99
}
100
}
101
102
/* SFRD takes care of discipline read and stack popping */
103
f->mode |= rcrv;
104
f->getr = rc;
105
if((r = SFRD(f,f->endb,r,f->disc)) >= 0)
106
{ r = f->endb - f->next;
107
break;
108
}
109
}
110
111
SFOPEN(f,local);
112
113
rcrv = (n == 0) ? (r > 0 ? (int)(*f->next++) : EOF) : (int)r;
114
115
SFMTXRETURN(f,rcrv);
116
}
117
118