Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/pzip/r2c.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1998-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
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
/*
23
* Glenn Fowler
24
* AT&T Research
25
*
26
* convert delimited/terminated flat file from
27
* row major to col major order
28
*/
29
30
static const char id[] = "\n@(#)$Id: r2c (AT&T Research) 1998-11-08 $\0\n";
31
32
#include <ast.h>
33
#include <ctype.h>
34
#include <error.h>
35
#include <ls.h>
36
#include <sfdcgzip.h>
37
38
typedef struct Col_s
39
{
40
struct Col_s* next;
41
Sfio_t* sp;
42
} Col_t;
43
44
static struct State_s
45
{
46
Col_t* cols;
47
Col_t* last;
48
49
size_t cache;
50
size_t window;
51
52
int delimiter;
53
int level;
54
int quote;
55
int terminator;
56
int test;
57
int verbose;
58
} state;
59
60
/*
61
* flush output to op
62
*/
63
64
static int
65
flush(Sfio_t* op)
66
{
67
register Col_t* col;
68
register size_t n;
69
70
if ((col = state.cols) && sfstrtell(col->sp))
71
{
72
do
73
{
74
n = sfstrtell(col->sp);
75
if (sfwrite(op, sfstrseek(col->sp, 0, SEEK_SET), n) != n || sfsync(op))
76
{
77
error(ERROR_SYSTEM|2, "write error");
78
return -1;
79
}
80
} while (col = col->next);
81
}
82
state.cache = state.window;
83
return 0;
84
}
85
86
/*
87
* convert one file from ip to op
88
*/
89
90
static int
91
r2c(const char* file, Sfio_t* ip, Sfio_t* op)
92
{
93
register char* s;
94
register char* e;
95
register int d;
96
register int q;
97
register int t;
98
register Col_t* col;
99
register size_t w;
100
register size_t n;
101
register size_t m;
102
char* b;
103
104
w = state.cache;
105
d = state.delimiter;
106
q = state.quote;
107
t = state.terminator;
108
while (s = sfgetr(ip, t, 0))
109
{
110
n = sfvalue(ip);
111
if (w < n)
112
{
113
if (n > state.window)
114
{
115
error(2, "%s: input record larger than window size", file);
116
return -1;
117
}
118
if (flush(op))
119
return -1;
120
}
121
w -= n;
122
col = state.cols;
123
for (;;)
124
{
125
if (!col)
126
{
127
if (!(col = newof(0, Col_t, 1, 0)) || !(col->sp = sfstropen()))
128
error(ERROR_SYSTEM|3, "out of space [column]");
129
if (!state.cols)
130
state.cols = col;
131
else if (state.last)
132
state.last->next = col;
133
state.last = col;
134
}
135
if (q && *s == q)
136
{
137
b = s;
138
e = s + n;
139
while (++b < e)
140
if (*b == q)
141
{
142
b++;
143
break;
144
}
145
m = b - s;
146
}
147
else if (e = memchr(s, d, n))
148
m = e - s + 1;
149
else
150
m = n;
151
if (sfwrite(col->sp, s, m) != m)
152
{
153
error(ERROR_SYSTEM|2, "%s: column write error");
154
return -1;
155
}
156
if (!e)
157
break;
158
s += m;
159
n -= m;
160
col = col->next;
161
}
162
}
163
if (sfgetr(ip, -1, 0))
164
{
165
error(2, "%s: last record incomplete", file);
166
return -1;
167
}
168
return 0;
169
}
170
171
main(int argc, char** argv)
172
{
173
char* file;
174
Sfio_t* ip;
175
176
error_info.id = "r2c";
177
state.delimiter = ':';
178
state.terminator = '\n';
179
state.window = 4 * 1024 * 1024;
180
state.level = 9;
181
for (;;)
182
{
183
switch (optget(argv, "d:[delimiter]l#[compression-level]q:[quote]t:[terminator]vw#[window-size]T#[test-mask]"))
184
{
185
case 'd':
186
state.delimiter = *opt_info.arg;
187
continue;
188
case 'l':
189
state.level = opt_info.num;
190
continue;
191
case 'q':
192
state.quote = *opt_info.arg;
193
continue;
194
case 't':
195
state.delimiter = *opt_info.arg;
196
continue;
197
case 'v':
198
state.verbose = 1;
199
continue;
200
case 'w':
201
state.window = opt_info.num;
202
continue;
203
case 'T':
204
state.test |= opt_info.num;
205
continue;
206
case '?':
207
error(ERROR_USAGE|4, opt_info.arg);
208
continue;
209
case ':':
210
error(2, opt_info.arg);
211
continue;
212
}
213
break;
214
}
215
argv += opt_info.index;
216
if (error_info.errors)
217
error(ERROR_USAGE|4, "%s", optusage(NiL));
218
state.cache = state.window;
219
if (state.level > 0 && sfdcgzip(sfstdout, state.level) < 0)
220
error(3, "output compress discipline error");
221
if (!*argv)
222
r2c("/dev/stdin", sfstdin, sfstdout);
223
else
224
while (file = *argv++)
225
{
226
if (streq(file, "-"))
227
{
228
file = "/dev/stdin";
229
ip = sfstdin;
230
}
231
else if (!(ip = sfopen(NiL, file, "r")))
232
{
233
error(ERROR_SYSTEM|2, "%s: cannot read", file);
234
continue;
235
}
236
r2c(file, ip, sfstdout);
237
if (ip != sfstdin)
238
sfclose(ip);
239
}
240
flush(sfstdout);
241
return error_info.errors != 0;
242
}
243
244