/* * Created by PyramIDE. * User: フランスのトトロ aka (David RENÉ) * Date: 06/05/2017 * Time: 17:33 * © Calexium */ 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)) }.