4
/* Discipline to treat a contiguous segment of a stream as a stream
5
** in its own right. The hard part in all this is to allow multiple
6
** segments of the stream to be used as substreams at the same time.
8
** Written by David G. Korn and Kiem-Phong Vo (03/18/1998)
11
typedef struct _subfile_s
13
Sfdisc_t disc; /* sfio discipline */
14
Sfio_t* parent; /* parent stream */
15
Sfoff_t offset; /* starting offset */
16
Sfoff_t extent; /* size wanted */
17
Sfoff_t here; /* current seek location */
21
static ssize_t streamio(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc, int type)
23
static ssize_t streamio(f, buf, n, disc, type)
32
reg Sfoff_t here, parent;
35
su = (Subfile_t*)disc;
37
/* read just what we need */
38
if(su->extent >= 0 && (ssize_t)n > (io = (ssize_t)(su->extent - su->here)) )
43
/* save current location in parent stream */
44
parent = sfseek(su->parent,(Sfoff_t)0,1);
47
here = su->here + su->offset;
48
if(sfseek(su->parent,here,0) != here)
51
{ if(type == SF_WRITE)
52
io = sfwrite(su->parent,buf,n);
53
else io = sfread(su->parent,buf,n);
58
/* restore parent current position */
59
sfseek(su->parent,parent,0);
65
static ssize_t streamwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
67
static ssize_t streamwrite(f, buf, n, disc)
74
return streamio(f,(Void_t*)buf,n,disc,SF_WRITE);
78
static ssize_t streamread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
80
static ssize_t streamread(f, buf, n, disc)
87
return streamio(f,buf,n,disc,SF_READ);
91
static Sfoff_t streamseek(Sfio_t* f, Sfoff_t pos, int type, Sfdisc_t* disc)
93
static Sfoff_t streamseek(f, pos, type, disc)
101
reg Sfoff_t here, parent;
103
su = (Subfile_t*)disc;
117
{ parent = sfseek(su->parent,(Sfoff_t)0,1);
118
if((here = sfseek(su->parent,(Sfoff_t)0,2)) < 0)
120
else here -= su->offset;
121
sfseek(su->parent,parent,0);
129
if(pos < 0 || (su->extent >= 0 && pos >= su->extent))
132
return (su->here = pos);
136
static streamexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
138
static streamexcept(f, type, data, disc)
145
if(type == SF_FINAL || type == SF_DPOP)
151
int sfdcsubstream(Sfio_t* f, Sfio_t* parent, Sfoff_t offset, Sfoff_t extent)
153
int sfdcsubstream(f, parent, offset, extent)
154
Sfio_t* f; /* stream */
155
Sfio_t* parent; /* parent stream */
156
Sfoff_t offset; /* offset in parent stream */
157
Sfoff_t extent; /* desired size */
163
/* establish that we can seek to offset */
164
if((here = sfseek(parent,(Sfoff_t)0,1)) < 0 || sfseek(parent,offset,0) < 0)
166
else sfseek(parent,here,0);
168
if(!(su = (Subfile_t*)malloc(sizeof(Subfile_t))) )
171
su->disc.readf = streamread;
172
su->disc.writef = streamwrite;
173
su->disc.seekf = streamseek;
174
su->disc.exceptf = streamexcept;
179
if(sfdisc(f, (Sfdisc_t*)su) != (Sfdisc_t*)su)