:- ensure_loaded( library(csv) ).
% :- lib( stoics_lib:en_list/2 ).
/** mtx_read_table( +CsvF, +RowsName, -Table, +OptS ).
Reads a table in from a file (CsvF). A table is a delimited file in which the first row is one short than the rest.
RowsName is added as the first argument in the read-in Table's first row.
OptS
* match(Match=true)
whether to match_arity(Match) rows read in (see csv//2 options).
* sep(Sep=_)
the mtx/2 version of separator(Sep) option of csv//2 (mtx_sep/2). Defaults to csv//2 version which is based on filename extension.
Any other OptS are passed to csv//2.
As per mtx/3 convention OptS can be a single option (un-listed) or a list of options.
==
?- tmp_file( testo, TmpF ),
csv_write_file( TmpF, [row(c_a,c_b),row(1,a,b),row(2,aa,bb)], [match_arity(false),separator(0'\t)] ),
mtx_read_table( TmpF, samples, Tbl, sep(tab) ).
TmpF = '/tmp/pl_testo_12445_0',
Tbl = [row(samples, c_a, c_b), row(1, a, b), row(2, aa, bb)].
==
@author nicos angelopoulos
@version 0.1 2018/2/3
@see mtx_sep/2, csv//2
*/
mtx_read_table( File, RowsName, Table, OptionS ) :-
en_list( OptionS, Options ),
( select_option(sep(MtxSep),Options,Options0) ->
mtx_sep( MtxSep, CsvSep ),
Options1 = [separator(CsvSep)|Options0]
;
csv:default_separator( File, Options, Options1 )
),
select_option( match(MatchPrv), Options1, Options2, _ ),
( var(MatchPrv) -> Match = true; Match = MatchPrv ),
csv:make_csv_options([match_arity(Match)|Options2], RecOptionsPrv, Options3),
setup_call_cleanup(
open(File, read, Stream, Options3),
(
csv_read_row(Stream, Row0, RecOptionsPrv),
( Match == true ->
% fixme: this hacking:
RecOptionsPrv = csv_options(CopA,CopB,CopC,CopD,CopE,CopF,HdrAri,CopH,CopI),
RowsAri is HdrAri + 1,
RecOptions = csv_options(CopA,CopB,CopC,CopD,CopE,CopF,RowsAri,CopH,CopI)
;
RecOptionsPrv = RecOptions
),
functor( Row0, _, HdrArity ),
Arity is HdrArity + 1,
Row0 =.. [Row0Nm|Row0Args],
Hdr =.. [Row0Nm,RowsName|Row0Args],
mtx_read_table_stream_rows(Hdr, Stream, Match, Arity, Table, RecOptions)
),
close(Stream)).
mtx_read_table_stream_rows( end_of_file, _Stream, _Match, _Arity, Rows, _Opts ) :-
!,
Rows = [].
mtx_read_table_stream_rows(Row, Stream, Match, Arity, [Row|Rows], Opts ) :-
mtx_read_table_row_match_arity( Match, Arity, Row ),
csv_read_row( Stream, NxtRow, Opts ),
mtx_read_table_stream_rows(NxtRow, Stream, Match, Arity, Rows, Opts ).
mtx_read_table_row_match_arity( false, _Arity, _Row ).
mtx_read_table_row_match_arity( true, Arity, Row ) :-
functor( Row, _, Rarity ),
( Rarity =:= Arity -> true; throw(arity_mismatch(Arity,Rarity,Row)) ).