csv_tools.anubis
3.33 KB
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
* Created by PyramIDE.
* User: フランスのトトロ aka (David RENÉ)
* Date: 06/05/2017
* Time: 17:33
* © David RENÉ
*/
read tools/basis.anubis
read system/string.anubis
read system/data_io.anubis
read tools/line_reader.anubis
public define (List(String), Bool, List(Word8))
csv_split_by_tokens
(
List(Word8) line, // list of left char to parse in the line
List(Word8) tokens, // list of tokens as separator
List(Word8) current, // current column chars
List(String) so_far, // list of already parsed column
Bool inside_string // flag which indicate we are inside string
) =
if line is
{
[] then
if length(current) > 0 then
if inside_string then
(reverse(so_far), inside_string, current)
else
(reverse([ implode(reverse(current)) . so_far]), false, [])
else
(reverse(so_far), inside_string, []),
[ char . t ] then
if char = '\"' then
with double_delimiter = if t is
{
[] then false,
[char2 . t2] then char2 = char
},
if inside_string then
if double_delimiter then
csv_split_by_tokens(if t is [_ . t2] then t2 else [], tokens, [ char . current ], so_far, inside_string)
else
csv_split_by_tokens(t, tokens, current, so_far, false) // end of string
else
csv_split_by_tokens(t, tokens, current, so_far, true) // start of string
else if member(tokens, char) & inside_string = false then
csv_split_by_tokens( t, tokens, [], [ trim(implode(reverse(current))) . so_far], false)
else
csv_split_by_tokens( t, tokens, [ char . current ], so_far, inside_string)
}.
public define (List(String), Bool, List(Word8))
csv_split_by_tokens
(
String line,
List(Word8) tokens,
Bool inside_string
)=
csv_split_by_tokens(explode(line), tokens, [], [], inside_string).
/**
* Splits a line using token as separator, taking care of '"' as string delimiter.
* So all tokens found between two delimiter will be ignored.
* Return the list of elements and a boolean set to true if the EOL was found inside a string.
*/
public define (List(String), Bool, List(Word8))
csv_split
(
String line,
Word8 token,
Bool inside_string
)=
csv_split_by_tokens(explode(line), [token], [], [], inside_string).
public define Maybe((String, List(String)))
csv_read_line
(
Data_IO io,
Word8 separator,
Bool inside_string,
String full_line,
List(Word8) current_column,
List(String) so_far
) =
if (Maybe(String))read_line(io) is
{
failure then
if length(full_line) > 0 then
println("quitting csv_read_line (read_line failure)");
success((full_line, so_far))
else
failure,
success(line) then
if csv_split_by_tokens(explode(line), [separator], current_column, [], inside_string) is (all_values, should_continue, partial) then
if should_continue then
csv_read_line(io, separator, true, full_line + line + "\n", partial, so_far + all_values)
else
success((full_line + line, so_far + all_values))
}.