Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/disc/sfdcsubstr.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 "sfdchdr.h"
23
24
25
/* Discipline to treat a contiguous segment of a stream as a stream
26
** in its own right. The hard part in all this is to allow multiple
27
** segments of the stream to be used as substreams at the same time.
28
**
29
** Written by David G. Korn and Kiem-Phong Vo (03/18/1998)
30
*/
31
32
typedef struct _subfile_s
33
{
34
Sfdisc_t disc; /* sfio discipline */
35
Sfio_t* parent; /* parent stream */
36
Sfoff_t offset; /* starting offset */
37
Sfoff_t extent; /* size wanted */
38
Sfoff_t here; /* current seek location */
39
} Subfile_t;
40
41
#if __STD_C
42
static ssize_t streamio(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc, int type)
43
#else
44
static ssize_t streamio(f, buf, n, disc, type)
45
Sfio_t* f;
46
Void_t* buf;
47
size_t n;
48
Sfdisc_t* disc;
49
int type;
50
#endif
51
{
52
reg Subfile_t *su;
53
reg Sfoff_t here, parent;
54
reg ssize_t io;
55
56
su = (Subfile_t*)disc;
57
58
/* read just what we need */
59
if(su->extent >= 0 && (ssize_t)n > (io = (ssize_t)(su->extent - su->here)) )
60
n = io;
61
if(n <= 0)
62
return n;
63
64
/* save current location in parent stream */
65
parent = sfsk(f,(Sfoff_t)0,SEEK_CUR,disc);
66
67
/* read data */
68
here = su->here + su->offset;
69
if(sfsk(f,here,SEEK_SET,disc) != here)
70
io = 0;
71
else
72
{ if(type == SF_WRITE)
73
io = sfwr(f,buf,n,disc);
74
else io = sfrd(f,buf,n,disc);
75
if(io > 0)
76
su->here += io;
77
}
78
79
/* restore parent current position */
80
sfsk(f,parent,SEEK_SET,disc);
81
82
return io;
83
}
84
85
#if __STD_C
86
static ssize_t streamwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
87
#else
88
static ssize_t streamwrite(f, buf, n, disc)
89
Sfio_t* f;
90
Void_t* buf;
91
size_t n;
92
Sfdisc_t* disc;
93
#endif
94
{
95
return streamio(f,(Void_t*)buf,n,disc,SF_WRITE);
96
}
97
98
#if __STD_C
99
static ssize_t streamread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
100
#else
101
static ssize_t streamread(f, buf, n, disc)
102
Sfio_t* f;
103
Void_t* buf;
104
size_t n;
105
Sfdisc_t* disc;
106
#endif
107
{
108
return streamio(f,buf,n,disc,SF_READ);
109
}
110
111
#if __STD_C
112
static Sfoff_t streamseek(Sfio_t* f, Sfoff_t pos, int type, Sfdisc_t* disc)
113
#else
114
static Sfoff_t streamseek(f, pos, type, disc)
115
Sfio_t* f;
116
Sfoff_t pos;
117
int type;
118
Sfdisc_t* disc;
119
#endif
120
{
121
reg Subfile_t* su;
122
reg Sfoff_t here, parent;
123
124
su = (Subfile_t*)disc;
125
126
switch(type)
127
{
128
case SEEK_SET:
129
here = 0;
130
break;
131
case SEEK_CUR:
132
here = su->here;
133
break;
134
case SEEK_END:
135
if(su->extent >= 0)
136
here = su->extent;
137
else
138
{ parent = sfsk(f,(Sfoff_t)0,SEEK_CUR,disc);
139
if((here = sfsk(f,(Sfoff_t)0,SEEK_END,disc)) < 0)
140
return -1;
141
else here -= su->offset;
142
sfsk(f,parent,SEEK_SET,disc);
143
}
144
break;
145
default:
146
return -1;
147
}
148
149
pos += here;
150
if(pos < 0 || (su->extent >= 0 && pos >= su->extent))
151
return -1;
152
153
return (su->here = pos);
154
}
155
156
#if __STD_C
157
static int streamexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
158
#else
159
static int streamexcept(f, type, data, disc)
160
Sfio_t* f;
161
int type;
162
Void_t* data;
163
Sfdisc_t* disc;
164
#endif
165
{
166
if(type == SF_FINAL || type == SF_DPOP)
167
free(disc);
168
return 0;
169
}
170
171
#if __STD_C
172
Sfio_t* sfdcsubstream(Sfio_t* f, Sfio_t* parent, Sfoff_t offset, Sfoff_t extent)
173
#else
174
Sfio_t* sfdcsubstream(f, parent, offset, extent)
175
Sfio_t* f; /* stream */
176
Sfio_t* parent; /* parent stream */
177
Sfoff_t offset; /* offset in f */
178
Sfoff_t extent; /* desired size */
179
#endif
180
{
181
reg Sfio_t* sp;
182
reg Subfile_t* su;
183
reg Sfoff_t here;
184
185
/* establish that we can seek to offset */
186
if((here = sfseek(parent,(Sfoff_t)0,SEEK_CUR)) < 0 || sfseek(parent,offset,SEEK_SET) < 0)
187
return 0;
188
else sfseek(parent,here,SEEK_SET);
189
sfpurge(parent);
190
191
if (!(sp = f) && !(sp = sfnew(NIL(Sfio_t*), NIL(Void_t*), (size_t)SF_UNBOUND, dup(sffileno(parent)), parent->flags)))
192
return 0;
193
194
if(!(su = (Subfile_t*)malloc(sizeof(Subfile_t))))
195
{ if(sp != f)
196
sfclose(sp);
197
return 0;
198
}
199
memset(su, 0, sizeof(*su));
200
201
su->disc.readf = streamread;
202
su->disc.writef = streamwrite;
203
su->disc.seekf = streamseek;
204
su->disc.exceptf = streamexcept;
205
su->parent = parent;
206
su->offset = offset;
207
su->extent = extent;
208
209
if(sfdisc(sp, (Sfdisc_t*)su) != (Sfdisc_t*)su)
210
{ free(su);
211
if(sp != f)
212
sfclose(sp);
213
return 0;
214
}
215
216
return sp;
217
}
218
219