Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/disc/sfdcunion.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
/* Make a sequence of streams act like a single stream.
26
** This is for reading only.
27
**
28
** Written by Kiem-Phong Vo, [email protected], 03/18/1998.
29
*/
30
31
#define UNSEEKABLE 1
32
33
typedef struct _file_s
34
{ Sfio_t* f; /* the stream */
35
Sfoff_t lower; /* its lowest end */
36
} File_t;
37
38
typedef struct _union_s
39
{
40
Sfdisc_t disc; /* discipline structure */
41
short type; /* type of streams */
42
short c; /* current stream */
43
short n; /* number of streams */
44
Sfoff_t here; /* current location */
45
File_t f[1]; /* array of streams */
46
} Union_t;
47
48
#if __STD_C
49
static ssize_t unwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
50
#else
51
static ssize_t unwrite(f, buf, n, disc)
52
Sfio_t* f; /* stream involved */
53
Void_t* buf; /* buffer to read into */
54
size_t n; /* number of bytes to read */
55
Sfdisc_t* disc; /* discipline */
56
#endif
57
{
58
return -1;
59
}
60
61
#if __STD_C
62
static ssize_t unread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
63
#else
64
static ssize_t unread(f, buf, n, disc)
65
Sfio_t* f; /* stream involved */
66
Void_t* buf; /* buffer to read into */
67
size_t n; /* number of bytes to read */
68
Sfdisc_t* disc; /* discipline */
69
#endif
70
{
71
reg Union_t* un;
72
reg ssize_t r, m;
73
74
un = (Union_t*)disc;
75
m = n;
76
f = un->f[un->c].f;
77
while(1)
78
{ if((r = sfread(f,buf,m)) < 0 || (r == 0 && un->c == un->n-1) )
79
break;
80
81
m -= r;
82
un->here += r;
83
84
if(m == 0)
85
break;
86
87
buf = (char*)buf + r;
88
if(sfeof(f) && un->c < un->n-1)
89
f = un->f[un->c += 1].f;
90
}
91
return n-m;
92
}
93
94
#if __STD_C
95
static Sfoff_t unseek(Sfio_t* f, Sfoff_t addr, int type, Sfdisc_t* disc)
96
#else
97
static Sfoff_t unseek(f, addr, type, disc)
98
Sfio_t* f;
99
Sfoff_t addr;
100
int type;
101
Sfdisc_t* disc;
102
#endif
103
{
104
reg Union_t* un;
105
reg int i;
106
reg Sfoff_t extent, s;
107
108
un = (Union_t*)disc;
109
if(un->type&UNSEEKABLE)
110
return -1L;
111
112
if(type == 2)
113
{ extent = 0;
114
for(i = 0; i < un->n; ++i)
115
extent += (sfsize(un->f[i].f) - un->f[i].lower);
116
addr += extent;
117
}
118
else if(type == 1)
119
addr += un->here;
120
121
if(addr < 0)
122
return -1;
123
124
/* find the stream where the addr could be in */
125
extent = 0;
126
for(i = 0; i < un->n-1; ++i)
127
{ s = sfsize(un->f[i].f) - un->f[i].lower;
128
if(addr < extent + s)
129
break;
130
extent += s;
131
}
132
133
s = (addr-extent) + un->f[i].lower;
134
if(sfseek(un->f[i].f,s,0) != s)
135
return -1;
136
137
un->c = i;
138
un->here = addr;
139
140
for(i += 1; i < un->n; ++i)
141
sfseek(un->f[i].f,un->f[i].lower,0);
142
143
return addr;
144
}
145
146
/* on close, remove the discipline */
147
#if __STD_C
148
static int unexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
149
#else
150
static int unexcept(f,type,data,disc)
151
Sfio_t* f;
152
int type;
153
Void_t* data;
154
Sfdisc_t* disc;
155
#endif
156
{
157
if(type == SF_FINAL || type == SF_DPOP)
158
free(disc);
159
160
return 0;
161
}
162
163
#if __STD_C
164
int sfdcunion(Sfio_t* f, Sfio_t** array, int n)
165
#else
166
int sfdcunion(f, array, n)
167
Sfio_t* f;
168
Sfio_t** array;
169
int n;
170
#endif
171
{
172
reg Union_t* un;
173
reg int i;
174
175
if(n <= 0)
176
return -1;
177
178
if(!(un = (Union_t*)malloc(sizeof(Union_t)+(n-1)*sizeof(File_t))) )
179
return -1;
180
memset(un, 0, sizeof(*un));
181
182
un->disc.readf = unread;
183
un->disc.writef = unwrite;
184
un->disc.seekf = unseek;
185
un->disc.exceptf = unexcept;
186
un->n = n;
187
188
for(i = 0; i < n; ++i)
189
{ un->f[i].f = array[i];
190
if(!(un->type&UNSEEKABLE))
191
{ un->f[i].lower = sfseek(array[i],(Sfoff_t)0,1);
192
if(un->f[i].lower < 0)
193
un->type |= UNSEEKABLE;
194
}
195
}
196
197
if(sfdisc(f,(Sfdisc_t*)un) != (Sfdisc_t*)un)
198
{ free(un);
199
return -1;
200
}
201
202
return 0;
203
}
204
205