### ----------------------------------------------------
### -- Text::CSV
### -- Licenses: Artistic-2.0
### -- Authors: H.Merijn Brand (Tux)
### -- File: Text-CSV.pod
### ----------------------------------------------------
### -- Chunk 1 of 3
=begin pod

=encoding utf-8

=head1 DISCLAIMER

Note that updating these docs is an ongoing process and some perl5 idioms
might not have been translated yet into correct raku idiom. My bad. Sorry.
(Feedback welcome)

=head1 NAME

Text::CSV - comma-separated values manipulation routines

=head1 SYNOPSIS

 use Text::CSV;

 # Read whole file in memory
 my @aoa = csv(in => "data.csv");  # as array of arrays
 my @aoh = csv(in => "data.csv",
               headers => "auto"); # as array of hashes

 # Write array of arrays as csv file
 csv(in => @aoa, out => "file.csv", sep => ";");

 my @rows;
 # Read/parse CSV
 my $csv = Text::CSV.new;
 my $fh  = open "test.csv", :r, :!chomp;
 while (my @row = $csv.getline($fh)) {
     @row[2] ~~ m/pattern/ or next; # 3rd field should match
     @rows.push: @row;
     }
 $fh.close;

 # and write as CSV
 $fh = open "new.csv", :w;
 $csv.say($fh, $_) for @rows;
 $fh.close;

=head1 DESCRIPTION

Text::CSV provides facilities for the composition and decomposition of
comma-separated values. An instance of the Text::CSV class will combine
fields into a C<CSV> string and parse a C<CSV> string into fields.

The module accepts either strings or files as input and support the use of
user-specified characters (or sequences thereof) for delimiters, separators,
and escapes.

In all following documentation, C<WIP> stands for "Work In Progress" and
C<NYI> for "Not Yet Implemented". The goal is to get rid of all of those.

=head2 Embedded newlines

B<Important Note>: The default behavior is to accept only UTF-8 characters.

But you still have the problem that you have to pass a correct line to the
L</parse> method, which is more complicated from the usual point of usage:

 my $csv = Text::CSV.new;
 for lines() : eager {          #  WRONG!
     $csv.parse($_);
     my @fields = $csv.fields;
     }

this will break for several reasons. The default open mode is to C<chomp>
lines, which will also remove the newline sequence if that sequence is not
(part of) the newline at all. As the C<for> might read broken lines: it
does not care about the quoting. If you need to support embedded newlines,
the way to go is to B<not> pass L<C<eol>|/eol> in the parser (it accepts
C<\n>, C<\r>, B<and> C<\r\n> by default) and then

 my $csv = Text::CSV.new;
 my $io = open $file, :r, :!chomp;
 while (my $row = $csv.getline($io)) {
     my @fields = @$row;
     }

=head2 Binary data

For now, Text::CSV only accepts Unicode. Binary data is planned.

=head1 SPECIFICATION

While no formal specification for CSV exists, L<RFC 4180|https://datatracker.ietf.org/doc/html/rfc4180>
(I<1>) describes the common format and establishes  C<text/csv> as the MIME
type registered with the IANA. L<RFC 7111|https://datatracker.ietf.org/doc/html/rfc7111>
(I<2>) adds fragments to CSV.

Many informal documents exist that describe the C<CSV> format.   L<"How To:
The Comma Separated Value (CSV) File Format"|creativyst.com/Doc/Articles/CSV/CSV01.shtml>
(I<3>)  provides an overview of the  C<CSV>  format in the most widely used
applications and explains how it can best be used and supported.

 1) https://datatracker.ietf.org/doc/html/rfc4180
 2) https://datatracker.ietf.org/doc/html/rfc7111
 3) http://creativyst.com/Doc/Articles/CSV/CSV01.shtml

The basic rules are as follows:

B<CSV> is a delimited data format that has fields/columns separated by the
comma character and records/rows separated by newlines. Fields that contain
a special character (comma, newline, or double quote), must be enclosed in
double quotes. However, if a line contains a single entry that is the empty
string, it may be enclosed in double quotes. If a field's value contains a
double quote character it is escaped by placing another double quote
character next to it. The C<CSV> file format does not require a specific
character encoding, byte order, or line terminator format.

=over 2

=item *

Each record is a single line ended by a line feed (ASCII/C<LF>=C<0x0A>) or
a carriage return and line feed pair (ASCII/C<CRLF>=C<0x0D 0x0A>), however,
line-breaks may be embedded.

=item *

Fields are separated by commas.

=item *

Allowable characters within a C<CSV> field include C<0x09> (C<TAB>) and the
inclusive range of C<0x20> (space) through C<0x7E> (tilde). In binary mode
all characters are accepted, at least in quoted fields.

=item *

A field within C<CSV> must be surrounded by double-quotes to contain a
separator character (comma).

=back

Though this is the most clear and restrictive definition, Text::CSV is way
more liberal than this, and allows extension:

=over 2

=item *

Line termination by a single carriage return is accepted by default

=item *

The separation, escape, and escape can be any valid Unicode sequence.

=item *

A field in C<CSV> must be surrounded by double-quotes to make an embedded
double-quote, represented by a pair of consecutive double-quotes, valid.
You may additionally use the sequence C<"0> for representation of a NULL
byte. Using C<0x00> is just as valid.

=item *

Several violations of the above specification may be lifted by passing some
options as attributes to the object constructor.

=back

=head1 METHODS

=head2 version
X<version>

Returns the current module version.

=head2 new
X<new>

Returns a new instance of class Text::CSV. The attributes are described by
the optional named parameters

 my $csv = Text::CSV.new(attributes ...);

The following attributes are available:

=over 4

=item eol
X<eol>

 my $csv = Text::CSV.new(eol => "\r\n");
           $csv.eol(Str);
 my $eol = $csv.eol;

The end-of-line string to add to rows for L</print> or the record separator
for L</getline>.

When not set in a B<parser> instance, the default behavior is to accept
C<\n>, C<\r>, and C<\r\n>, so it is probably safer to not specify C<eol> at
all. Passing C<Str> or the empty string behave the same.

As raku interprets C<\r\n> as a single grapheme in input, it is dissuaded
to use C<\r\n> as C<eol> when parsing. Please choose C<Str> instead.

When not passed in a B<generating> instance, records are not terminated at
all, so it is probably wise to pass something you expect. A safe choice for
C<eol> on output is either C<\n> or C<\r\n>.

Common values for C<eol> are C<"\012"> (C<\n> or Line Feed), C<"\015\012">
(C<\r\n> or Carriage Return, Line Feed), and C<"\015"> (C<\r> or Carriage
Return).

=item sep
X<sep>

=item sep_char
X<sep_char>

=item sep-char
X<sep-char>

=item separator
X<separator>

 my $csv = Text::CSV.new(sep => ";");
           $csv.sep("\x[ff0c]"); # FULLWIDTH COMMA
 my $sep = $csv.sep;

The sequence used to separate fields, by default a comma: (C<,>). This
sequence is required and cannot be disabled.

The separation sequence can not be equal to the quote sequence, the
escape sequence or the newline sequence.

See also L</CAVEATS>

=item quote
X<quote>

=item quote_char
X<quote_char>

=item quote-char
X<quote-char>

 my $csv = Text::CSV.new(quote => "'");
           $csv.quote("\x[ff02]); # FULLWIDTH QUOTATION MARK
           $csv.quote(Str);
 my $quo = $csv.quote;

The sequence to quote fields containing blanks or binary data, by default
the double quote character (C<">). A value of C<Str> disables quotation
(for simple cases only).

The quotation sequence can not be equal to the separation sequence or the
newline sequence.

See also L</CAVEATS>

=item escape
X<escape>

=item escape_char
X<escape_char>

=item escape-char
X<escape-char>

 my $csv = Text::CSV.new(escape => "\\");
           $csv.escape("\x[241b]");  # SYMBOL FOR ESCAPE
           $csv.escape(Str);
 my $esc = $csv.escape;

The sequence to escape certain characters inside quoted fields.

The C<escape> defaults to being the double-quote mark (C<">). In other
words the same as the default sequence for L<C<quote>|/quote>. This means
that doubling the quote mark in a field escapes it:

 "foo","bar","Escape ""quote mark"" with two ""quote marks""","baz"

If you change L<C<quote>|/quote> without changing C<escape>, C<escape> will
still be the double-quote (C<">). If instead you want to escape
L<C<quote>|/quote> by doubling it you will need to also change C<escape> to
be the same as what you have changed L<C<quote>|/quote> to.

The escape sequence can not be equal to the separation sequence.

=item binary
X<binary>

WIP: Default is True. Non-UTF-8 real binary (Blob) does not yet parse.
Opening the resource with encoding utf8-c8 is most likely the way to go.

 my $csv = Text::CSV.new(:binary);
           $csv.binary(False);
 my $bin = $csv.binary;

If this attribute is C<True>, you may use binary data in quoted fields,
including line feeds, carriage returns and C<NULL> bytes. (The latter could
be escaped as C<"0>.) By default this feature is on.

Note that valid Unicode (UTF-8) is not considered binary.

=item strict
X<strict>

 my $csv = Text::CSV.new(:strict);
           $csv.strict(False);
 my $flg = $csv.strict;

If set to True, any row that parses to a different number of columns than
the previous row will cause the parser to throw error 2014.

=item formula-handling
X<formula-handling>

=item formula_handling
X<formula_handling>

=item formula
X<formula>

 my $csv = Text::CSV.new(formula => "none");
         $csv.formula("none");
 my $f = $csv.formula;

This defines the behavior of fields containing I<formulas>. As formulas are
considered dangerous in spreadsheets, this attribute can define an optional
action to be taken if a field starts with an equal sign (C<=>).

For purpose of code-readability, this can also be written as

 my $csv = Text::CSV.new(formula-handling => "none"});
         $csv.formula-handling("none");
 my $f = $csv.formula-handling;

or

 my $csv = Text::CSV.new(formula_handling => "none"});
         $csv.formula_handling("none");
 my $f = $csv.formula_handling;

Possible values for this attribute are

=over 2

=item none

Take no specific action. This is the default.

 $csv.formula("none");

=item die

Cause the process to C<die> whenever a leading C<=> is encountered.

 $csv.formula("die");

=item croak

Cause the process to C<die> whenever a leading C<=> is encountered.

 $csv.formula("croak");

This option just exists for perl5 compatibility.

=item diag

Report position and content of the field whenever a leading C<=> is found.
The value of the field is unchanged.

 $csv.formula("diag");

=item empty

Replace the content of fields that start with a C<=> with the empty string.

 $csv.formula("empty");
 $csv.formula("");

=item undef

Replace the content of fields that start with a C<=> with C<Str>.

 $csv.formula("undef");
 $csv.formula(Str);

=back

All other values will throw an exception with error code 1500.

=item skip_empty_rows
X<skip_empty_rows>

=item skip-empty-rows
X<skip-empty-rows>

Defines optional actions for empty rows

 my $csv = Text::CSV.new(skip_empty_rows => False);
           $csv.skip_empty_rows(True);
 my $ser = $csv.skip-empty-rows;

Possible values are

=over 2

=item 0 | False

This is the default. An empty line is seen as a single empty field.

=item 1 | True | "skip"

Empty lines are ignored.

=item 2 | "stop" | "eof"

Empty lines cause the parse to stop immediately without any error ignoring
the rest of the data.

=item 3 | "die"

Empty lines cause the parse to stop immediately with an exception.

=item 5 | "error"

Empty lines cause the parse to stop immediately with error 2015 ("Empty row")

=item callback

On an empty row, the callback is invoked to get alternative data to use
instead. The callback is expected to return a single string in valid CSV
format.

=back

=item auto_diag
X<auto_diag>

=item auto-diag
X<auto-diag>

 my $csv = Text::CSV.new(auto_diag => False);
           $csv.auto_diag(True);
 my $a-d = $csv.auto_diag;

Set this attribute to a number between C<1> and C<9> causes L</error_diag>
to be automatically called in void context upon errors. The value C<True>
evaluates to C<1>.

In case of error C<2012 - EOF>, this call will be void.

If C<auto_diag> is set to a numeric value greater than C<1>, it will C<die>
on errors instead of C<warn>.

=item diag_verbose
X<diag_verbose>

=item diag-verbose
X<diag-verbose>

 my $csv = Text::CSV.new(diag_verbose => 1);
           $csv.diag_verbose(2);
 my $d-v = $csv.diag_verbose;

Set the verbosity of the output triggered by C<auto_diag>.

WIP: Does not add any information yet.

=item blank_is_undef
X<blank_is_undef>

=item blank-is-undef
X<blank-is-undef>

 my $csv = Text::CSV.new(:blank_is_undef);
           $csv.blank_is_undef(False);
 my $biu = $csv.blank_is_undef;

Under normal circumstances, C<CSV> data makes no distinction between quoted-
and unquoted empty fields. These both end up in an empty string field once
read, thus

 1,"",," ",2

is read as

 [ "1", "", "", " ", "2" ]

When I<writing> C<CSV> files with L<C<always_quote>|/always_quote> set, the
unquoted I<empty> field is the result of an undefined value. To enable this
distinction when I<reading> C<CSV> data, the C<blank_is_undef> attribute
will cause unquoted empty fields to be set to C<Str>, causing the above
to be parsed as

 [ "1", "", Str, " ", "2" ]

=item empty_is_undef
X<empty_is_undef>

=item empty-is-undef
X<empty-is-undef>

 my $csv = Text::CSV.new(:empty_is_undef);
           $csv.empty_is_undef(False);
 my $eiu = $csv.empty_is_undef;

Going one step further than L<C<blank_is_undef>|/blank_is_undef>, this
attribute causes all empty fields to return as C<Str>, so

 1,"",," ",2

is read as

 [ 1, Str, Str, " ", 2 ]

Note that this effects only fields that are originally empty, not fields
that are empty after stripping allowed whitespace. YMMV.

=item allow_whitespace
X<allow_whitespace>

=item allow-whitespace
X<allow-whitespace>

 my $csv = Text::CSV.new(:allow_whitespace);
           $csv.allow_whitespace(False);
 my $a-w = $csv.allow_whitespace;

When this option is set to C<True>, the whitespace (C<TAB>'s and C<SPACE>'s)
surrounding the separation sequence is removed when parsing. If either
C<TAB> or C<SPACE> is one of the three major sequences L<C<sep>|/sep>,
L<C<quote>|/quote>, or L<C<escape>|/escape> it will not be considered
whitespace.

Now lines like:

 1 , "foo" , bar , 3 , zapp

are parsed as valid C<CSV>, even though it violates the C<CSV> specs.

Note that B<all> whitespace is stripped from both start and end of each
field. That would make it I<more> than a I<feature> to enable parsing bad
C<CSV> lines, as

 1,   2.0,  3,   ape  , monkey

will now be parsed as

 [ "1", "2.0", "3", "ape", "monkey" ]

even if the original line was perfectly acceptable C<CSV>.

=item allow_loose_quotes
X<allow_loose_quotes>

=item allow-loose-quotes
X<allow-loose-quotes>

 my $csv = Text::CSV.new(:allow_loose_quotes);
           $csv.allow_loose_quotes(False);
 my $alq = $csv.allow_loose_quotes;

By default, parsing unquoted fields containing L<C<quote>|/quote>'s like

 1,foo "bar" baz,42

would result in parse error 2034. Though it is still bad practice to allow
this format, we cannot help the fact that some vendors make their
applications spit out lines styled this way.

If there is B<really> bad C<CSV> data, like

 1,"foo "bar" baz",42

or

 1,""foo bar baz"",42

there is a way to get this data-line parsed and leave the quotes inside the
quoted field as-is. This can be achieved by setting C<allow_loose_quotes>
B<AND> making sure that the L<C<escape>|/escape> is I<not> equal to
L<C<quote>|/quote>.

=item allow_loose_escapes
X<allow_loose_escapes>

=item allow-loose-escapes
X<allow-loose-escapes>

 my $csv = Text::CSV.new(:allow_loose_escapes);
           $csv.allow_loose_escapes(False);
 my $ale = $csv.allow_loose_escapes;

Parsing fields that have L<C<escape>|/escape> sequences that escape
characters that do not need to be escaped, like:

 my $csv = Text::CSV.new(escape_char => "\\");
 $csv.parse(q{1,"my bar\'s",baz,42});

would result in parse returning C<False> with reason 2025. Though it is bad
practice to allow this format, this attribute enables you to treat all
escape sequences equal.

=item allow_unquoted_escape
X<allow_unquoted_escape>

=item allow-unquoted-escape
X<allow-unquoted-escape>

 my $csv = Text::CSV.new(:allow_unquoted_escape);
           $csv.allow_unquoted_escape(False);
 my $aue = $csv.allow_unquoted_escape;

A backward compatibility issue where L<C<escape>|/escape> differs from
L<C<quote>|/quote> prevents L<C<escape>|/escape> to be in the first
position of a field. If L<C<quote>|/quote> is equal to the default C<"> and
L<C<escape>|/escape> is set to C<\>, this would be illegal:

 1,\0,2

Setting this attribute to C<True> might help to overcome issues with
backward compatibility and allow this style.

=item always_quote
X<always_quote>

=item always-quote
X<always-quote>

 my $csv = Text::CSV.new(:always_quote);
         $csv.always_quote(False);
 my $f = $csv.always_quote;

By default the generated fields are quoted only if they I<need> to be. For
example, if they contain the separator sequence. If you set this attribute
to C<1> then I<all> defined fields will be quoted. (undefined (C<Str>)
fields are not quoted, see L</blank_is_undef>). This makes it quite often
easier to handle exported data in external applications. (Poor creatures
who are better to use Text::CSV. :)

=item quote_empty
X<quote_empty>

=item quote-empty
X<quote-empty>

 my $csv = Text::CSV.new(:quote_empty);
           $csv.quote_empty(False);
 my $q-s = $csv.quote_empty;

By default the generated fields are quoted only if they I<need> to be. An
empty defined field does not need quotation. If you set this attribute to
C<True> then empty defined fields will be quoted. See also
L<C<always_quote>|/always_quote>.

=item quote_space
X<quote_space>

=item quote-space
X<quote-space>

 my $csv = Text::CSV.new(:quote_space);
           $csv.quote_space(False);
 my $q-s = $csv.quote_space;

By default, a space in a field would trigger quotation. As no rule exists
this to be forced in C<CSV>, nor any for the opposite, the default is
C<True> for safety. You can exclude the space from this trigger by setting
this attribute to C<False>.

=item escape_null
X<escape_null>

=item quote-null
X<quote-null>

 my $csv = Text::CSV.new(:escape_null);
           $csv.escape_null(False);
 my $q-n = $csv.escape_null;

By default, a C<NULL> byte in a field would be escaped. This option enables
you to treat the C<NULL> byte as a simple binary character in binary mode
(the C<< binary => True >> is set). The default is C<True>. You can prevent
C<NULL> escapes by setting this attribute to C<False>.

=item quote_binary
X<quote_binary>

=item quote-binary
X<quote-binary>

 my $csv = Text::CSV.new(:quote_binary);
           $csv.quote_binary(False);
 my $q-b = $csv.quote_binary;

By default, all "unsafe" bytes inside a string cause the combined field to
be quoted. By setting this attribute to C<False>, you can disable that
trigger for bytes >= C<0x7F>. (WIP)

=item keep_meta
X<keep_meta>

=item keep-meta
X<keep-meta>

 my $csv = Text::CSV.new(:keep_meta);
           $csv.keep_meta(False);
 my $k-m = $csv.keep_meta_info;

By default, the parsing of input records is as simple and fast as possible.
However, some parsing information - like quotation of the original field -
is lost in that process. Setting this flag to true enables retrieving that
information after parsing with the methods L</meta_info>, L</is_quoted>,
and L</is_binary> described below. Default is C<False> for ease of use.

If C<keep-meta> is set to C<True>, the returned fields are not of type
C<Str> but of type L<C<CSV::Field>|/CSV::Field>.

=item undef_str
X<undef_str>

=item undef-str
X<undef-str>

NYI - this should replace undefined values in generating CSV

=item comment_str
X<comment_str>

=item comment-str
X<comment-str>

 my $csv = Text::CSV.new(comment_str => "#");
         $csv.comment_str (Str);
 my $s = $csv.comment_str;

This attribute optionally defines a string to be recognized as comment. If
this attribute is defined, all lines starting with this sequence will not
be parsed as CSV but skipped as comment.

This attribute has no meaning when generating CSV.

=item types

NYI

A set of column types; the attribute is immediately passed to the L</types>
method.

=item callbacks
X<callbacks>

See the L</Callbacks> section below.

=back

To sum it up,

 $csv = Text::CSV.new;

is equivalent to

 $csv = Text::CSV.new(
     eol                   => Nil, # \r, \n, or \r\n
     sep                   => ',',
     quote                 => '"',
     escape                => '"',
     binary                => True,
     auto-diag             => False,
     diag-verbose          => 0,
     blank-is-undef        => False,
     empty-is-undef        => False,
     allow-whitespace      => False,
     allow-loose-quotes    => False,
     allow-loose-escapes   => False,
     allow-unquoted-escape => False,
     always-quote          => False,
     quote-space           => True,
     escape-null           => True,
     quote-binary          => True,
     keep-meta             => False,
     strict                => False,
     formula               => "none",
     undef-str             => Str,
     comment-str           => Str,
     types                 => Nil,
     callbacks             => Nil,
     });

For all of the above mentioned flags, an accessor method is available where
you can inquire the current value, or change the value

 my $quote = $csv.quote;
 $csv.binary(True);

It is not wise to change these settings halfway through writing C<CSV> data
to a stream. If however you want to create a new stream using the available
C<CSV> object, there is no harm in changing them.

If the L</new> constructor call fails, an exception of type C<CSV::Diac> is
thrown with the reason like the L</error_diag> method would return:

 my $e;
 {   $csv = Text::CSV.new(ecs_char => ":") or
     CATCH { default { $e = $_; }}
     }
 $e and $e.message.say;

The message will be a string like

 "INI - Unknown attribute 'ecs_char'"

=head2 print
X<print>

 $status = $csv.print($io,  $fld, ... );
 $status = $csv.print($io, ($fld, ...));
 $status = $csv.print($io, [$fld, ...]);
 $status = $csv.print($io,  @fld      );

 $csv.column_names(%fld.keys); # or use a subset
 $status = $csv.print($io,  %fld      );

Similar to L</combine> + L</string> + L</print>, but much more efficient.
It takes an IO object and any number of arguments interpreted as fields.
The resulting string is immediately written to the C<$io> stream.

NYI: no fields in combination with L</bind_columns>, like

 $csv.bind_columns(\($foo, $bar));
 $status = $csv.print($fh);

A benchmark showed this order of preference, but the difference is within
noise range:

 my @data = ^20;
 $csv.print($io,   @data  );   # 2.6 sec
 $csv.print($io, [ @data ]);   # 2.7 sec
 $csv.print($io,    ^20   );   # 2.7 sec
 $csv.print($io,  \@data  );   # 2.8 sec

=head2 say
X<say>

Is the same a sL</print> where L<C<eol>|/eol> defaults to C<$*OUT.nl>.

 $status = $csv.say($io,  $fld, ... );
 $status = $csv.say($io, ($fld, ...));
 $status = $csv.say($io, [$fld, ...]);
 $status = $csv.say($io,  @fld      );

 $csv.column_names(%fld.keys); # or use a subset
 $status = $csv.say($io,  %fld      );

=head2 combine
X<combine>

 $status = $csv.combine(@fields);
 $status = $csv.combine($fld, ...);
 $status = $csv.combine(\@fields);

This method constructs a C<CSV> row from C<@fields>, returning success or
failure. Failure can result from lack of arguments or an argument that
contains invalid data. Upon success, L</string> can be called to retrieve
the resultant C<CSV> string. Upon failure, the value returned by L</string>
is undefined and L</error_input> could be called to retrieve the invalid
argument. (WIP)

=head2 string
X<string>

 $line = $csv.string;

This method returns the input to L</parse> or the resultant C<CSV> string
of L</combine>, whichever was called more recently. If L<C<eol>|/eol> is
defined, it is added to the string.

=head2 getline
X<getline>

 @row = $csv.getline($io);
 @row = $csv.getline($io,  :meta);
 @row = $csv.getline($str);
 @row = $csv.getline($str, :meta);

This is the counterpart to L</print>, as L</parse> is the counterpart to
L</combine>: it parses a row from the C<$io> handle or C<$str> using the
L</getline> method associated with C<$io> (or the internal temporary IO
handle used to read from the string as if it were an IO handle) and parses
this row into an array. This array is returned by the function or C<Array>
for failure. When C<$io> does not support C<getline>, you are likely to hit
errors.

NYI: When fields are bound with L</bind_columns> the return value is a
reference to an empty list.

=head2 getline_all
=head2 getline-all
X<getline_all>
X<getline-all>

 @rows = $csv.getline_all($io);
 @rows = $csv.getline_all($io,                   :meta);
 @rows = $csv.getline_all($io, $offset);
 @rows = $csv.getline_all($io, $offset,          :meta);
 @rows = $csv.getline_all($io, $offset, $length);
 @rows = $csv.getline_all($io, $offset, $length, :meta);

This will return a list of L<getline($io)|/getline> results.
If C<$offset> is negative, as with C<splice>, only the last C<abs($offset)>
records of C<$io> are taken into consideration.

Given a CSV file with 10 lines:

 lines call
 ----- ---------------------------------------------------------
 0..9  $csv.getline_all($io)         # all
 0..9  $csv.getline_all($io,  0)     # all
 8..9  $csv.getline_all($io,  8)     # start at 8
 -     $csv.getline_all($io,  0,  0) # start at 0 first 0 rows
 0..4  $csv.getline_all($io,  0,  5) # start at 0 first 5 rows
 4..5  $csv.getline_all($io,  4,  2) # start at 4 first 2 rows
 8..9  $csv.getline_all($io, -2)     # last 2 rows
 6..7  $csv.getline_all($io, -4,  2) # first 2 of last  4 rows

=head2 getline_hr
=head2 getline-hr
X<getline_hr>
X<getline-hr>

The L</getline_hr> and L</column_names> methods work together to allow you
to have rows returned as hashes instead of arrays. You must invoke
L</column_names> first to declare your column names.

 $csv.column_names(< code name price description >);
 %hr = $csv.getline_hr($str, :meta);
 %hr = $csv.getline_hr($io);
 say "Price for %hr<name> is %hr<price> \c[EURO SIGN]";

L</getline_hr> will fail if invoked before L</column_names>.

=head2 getline_hr_all
=head2 getline-hr-all
X<getline_hr_all>
X<getline-hr-all>

 @rows = $csv.getline_hr_all($io);
 @rows = $csv.getline_hr_all($io,                   :meta);
 @rows = $csv.getline_hr_all($io, $offset);
 @rows = $csv.getline_hr_all($io, $offset,          :meta);
 @rows = $csv.getline_hr_all($io, $offset, $length);
 @rows = $csv.getline_hr_all($io, $offset, $length, :meta);

This will return a list of L<getline_hr($io)|/getline_hr> results.

=head2 parse
X<parse>

 $status = $csv.parse($line);

This method decomposes a C<CSV> string into fields, returning success or
failure. Failure can result from a lack of argument or improper format in
the given C<CSV> string. Upon success, invoke L</fields> or L</strings> to
get the decomposed fields. Upon failure these methods shall not be trusted
to return reliable data.

NYI: You may use the L</types> method for setting column types. See
L</types>' description below.

=head2 fragment
X<fragment>

This function implements L<RFC7111|https://datatracker.ietf.org/doc/html/rfc7111>
(URI Fragment Identifiers for the text/csv Media Type).

 my @rows = $csv.fragment($io, $spec);

In specifications, C<*> is used to specify the I<last> item, a dash (C<->)
to indicate a range. All indices are C<1>-based: the first row or column
has index C<1>. Selections can be combined with the semi-colon (C<;>).

When using this method in combination with L</column_names>, the returned
array will be a list of hashes instead of an array of arrays. A disjointed
cell-based combined selection might return rows with different number of
columns making the use of hashes unpredictable.

 $csv.column_names(< Name Age >);
 my @rows = $csv.fragment($io, "row=3;8");

Note that for C<col="..">, the column names are the names for I<before> the
selection is taken to make it more consistent with reading possible headers
from the first line of the CSV datastream.

 $csv,column_names(< foo bar >);  # WRONG
 $csv.fragment($io, "col=3");

would set the column names for the first two columns that are then skipped
in the fragment. To skip the unwanted columns, use placeholders.

 $csv.column_names(< x x Name >);
 $csv.fragment($io, "col=3");

WIP: If the L</after_parse> callback is active, it is also called on every
line parsed and skipped before the fragment.

=over 2

=item row

 row=4
 row=5-7
 row=6-*
 row=1-2;4;6-*

=item col

 col=2
 col=1-3
 col=4-*
 col=1-2;4;7-*

=item cell

In cell-based selection, the comma (C<,>) is used to pair row and column

 cell=4,1

The range operator (C<->) using C<cell>s can be used to define top-left and
bottom-right C<cell> location

 cell=3,1-4,6

The C<*> is only allowed in the second part of a pair

 cell=3,2-*,2    # row 3 till end, only column 2
 cell=3,2-3,*    # column 2 till end, only row 3
 cell=3,2-*,*    # strip row 1 and 2, and column 1

Cells and cell ranges may be combined with C<;>, possibly resulting in rows
with different number of columns

 cell=1,1-2,2;3,3-4,4;1,4;4,1

Disjointed selections will only return selected cells. The cells that are
not specified will not be included in the returned set, not even as
C<Str>. As an example given a C<CSV> like

 11,12,13,...19
 21,22,...28,29
 :            :
 91,...97,98,99

with C<cell=1,