-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcsv.a68
89 lines (71 loc) · 1.98 KB
/
csv.a68
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# -*- coding: utf-8 -*- #
MODE CSVFIELD = STRING;
MODE CSVFIELDS = FLEX [0] CSVFIELD;
# OP +:= = (REF CSVFIELDS in out, CSVFIELD item) REF CSVFIELDS: (
HEAP [UPB in out + 1] CSVFIELD new;
new[:UPB in out] := in out;
new[UPB new] := item;
in out := new
); #
CHAR nl = REPR 10;
PROC read csv = (REF FILE csv, PROC (CSVFIELDS) VOID callback) VOID: (
CSVFIELD chunk := "";
INT chunk counter := 0;
INT fields count := 0;
INT line count := 0;
BOOL finished := FALSE;
PROC current = CHAR: chunk[chunk counter];
PROC next = CHAR: (
IF chunk counter = 0 OR chunk counter + 1 > UPB chunk THEN
getf(csv, ($gl$, chunk));
chunk +:= nl;
chunk counter := 0;
line count +:= 1
FI;
chunk counter +:= 1;
chunk[chunk counter]
);
next;
PROC parse = CSVFIELDS: (
on logical file end(csv, (REF FILE eof csv) BOOL: ( done eof; TRUE ));
CSVFIELDS fields := "";
BOOL in quotes := FALSE;
INT quote start := 0;
DO
IF in quotes THEN
IF current = """" THEN
# This probably would generate an error if eof
but I couldn't check it #
IF next = """" THEN
fields[UPB fields] := fields[UPB fields] + """";
next
ELSE
in quotes := FALSE
FI
ELSE
fields[UPB fields] := fields[UPB fields] + current;
next
FI
ELIF current = "," THEN fields +:= ""; next
ELIF current = """" THEN in quotes := TRUE; next
ELIF current = nl THEN next; GOTO done nl
ELSE fields[UPB fields] := fields[UPB fields] + current; next
FI
OD;
done eof:
finished := TRUE;
done nl:
IF fields count > 0 AND UPB fields /= fields count THEN
putf(stand error, ($"Error: unexpected number of fields ("g(-0)") in line "g(-0)" (expected "g(-0)")"l$, UPB fields, line count, fields count))
FI;
IF in quotes THEN
putf(stand error, ($"Error: unclosed quotes starting in line "g(-0)" column "g(-0)l$, line count, quote start))
FI;
fields
);
CSVFIELDS header = parse;
fields count := UPB header;
WHILE NOT finished DO
callback(parse)
OD
)