[Feature][Modem]Update MTK MODEM V1.6 baseline version: MOLY.NR15.R3.MD700.IVT.MP1MR3.MP.V1.6
MTK modem version: MT2735_IVT_MOLY.NR15.R3.MD700.IVT.MP1MR3.MP.V1.6.tar.gz
RF modem version: NA
Change-Id: I45a4c2752fa9d1a618beacd5d40737fb39ab64fb
diff --git a/mcu/tools/perl/Parse/CSV.pm b/mcu/tools/perl/Parse/CSV.pm
new file mode 100644
index 0000000..184149b
--- /dev/null
+++ b/mcu/tools/perl/Parse/CSV.pm
@@ -0,0 +1,463 @@
+package Parse::CSV;
+
+=pod
+
+=head1 NAME
+
+Parse::CSV - Highly flexible CVS parser for large files
+
+=head1 SYNOPSIS
+
+ # Simple headerless comma-seperated column parser
+ my $simple = Parse::CSV->new(
+ file => 'file.csv',
+ );
+ while ( my $array_ref = $simple->fetch ) {
+ # Do something...
+ }
+
+... or a more complex example...
+
+ # Parse a colon-seperated variables file from a handle as a hash
+ # based on headers from the first line.
+ # Then filter, so we emit objects rather than the plain hash.
+ my $objects = Parse::CSV->new(
+ handle => $io_handle,
+ sep_char => ';',
+ fields => 'auto',
+ filter => sub { My::Object->new( $_ ) },
+ );
+ while ( my $object = $objects->fetch ) {
+ $object->do_something;
+ }
+
+=head1 DESCRIPTION
+
+Surely the CPAN doesn't need yet another CSV parsing module.
+
+L<Text::CSV_XS> is the standard parser for CSV files. It is fast as hell,
+but unfortunately it can be a bit verbose to use.
+
+A number of other modules have attempted to put usability wrappers around
+this venerable module, but they have all focussed on parsing the entire
+file into memory at once.
+
+This method is fine unless your CSV files start to get large. Once that
+happens, the only existing option is to fall back on the relatively slow
+and heavyweight L<XML::SAXDriver::CSV> module.
+
+L<Parse::CSV> fills this functionality gap. It provides a flexible
+and light-weight streaming parser for large, extremely large, or
+arbitrarily large CSV files.
+
+=head2 Main Features
+
+B<Stream-Based Parser> - All parsing a line at a time.
+
+B<Array Mode> - Parsing can be done in simple array mode, returning
+a reference to an array if the columns are not named.
+
+B<Hash Mode> - Parsing can be done in hash mode, putting the data into
+a hash and return a reference to it.
+
+B<Filter Capability> - All items returned can be passed through a
+custom filter. This filter can either modify the data on the fly,
+or drop records you don't need.
+
+=head2 Writing Filters
+
+A L<Parse::CSV> filter is a subroutine reference that is passed the raw
+record as C<$_>, and should C<return> the alternative or modified record
+to return to the user.
+
+The null filter (does not modify or drop any records) looks like the
+following.
+
+ sub { $_ };
+
+A filter which reversed the order of the columns (assuming they are
+passed as an array) might look like the following.
+
+ sub { return [ reverse @$_ ] };
+
+To drop the record, you should return C<undef> from the filter. The
+parser will then keep pulling and parsing new records until one
+passes the filter.
+
+ # Only keep records where foo is true
+ sub { $_->{foo} ? $_ : undef }
+
+To signal an error, throw an exception
+
+ sub {
+ $_->{foo} =~ /bar/ or die "Assumption failed";
+ return $_;
+ }
+
+=head1 METHODS
+
+=cut
+
+use 5.005;
+use strict;
+use Carp ();
+use IO::File ();
+use Text::CSV_XS ();
+use Params::Util qw{ _STRING _ARRAY _HASH0 _CODELIKE _HANDLE };
+
+use vars qw{$VERSION};
+BEGIN {
+ $VERSION = '1.00';
+}
+
+
+
+
+
+#####################################################################
+# Constructor
+
+=pod
+
+=head2 new
+
+The C<new> constructor creates and initialise a new CSV parser.
+
+It takes a number of params.
+
+To specify the CSV data source, you should provide either the C<file>
+param, which should be the name of the file to read, or the C<handle>
+param, which should be a file handle to read instead.
+
+The actual parsing is done using L<Text::CSV_XS>. Any of it's
+constructor/parsing params can also be provided to this C<new> method,
+and they will be passed on.
+
+Alternatively, they can be passed as a single C<HASH> reference as the
+C<csv_attr> param. For example:
+
+ $parser = Parse::CSV->new(
+ file => 'file.csv',
+ csv_attr => {
+ sep_char => ';',
+ quote_char => "'",
+ },
+ );
+
+An optional C<fields> param can be provided, which should be an array
+reference containing the names of the columns in the CSV file.
+
+ $parser = Parse::CSV->new(
+ file => 'file.csv',
+ fields => [ 'col1', 'col2', 'col3' ],
+ );
+
+If the C<fields> param is provided, the parser will map the columns to a
+hash where the keys are the field names provided, and the values are the
+values found in the CSV file.
+
+If the C<fields> param is B<not> provided, the parser will return simple
+array references of the columns.
+
+If the C<fields> param is the string 'auto', the fields will be
+automatically determined by reading the first line of the CSV file and
+using those values as the field names.
+
+The optional C<filter> param will be used to filter the records if
+provided. It should be a C<CODE> reference or any otherwise callable
+scalar, and each value parsed (either array reference or hash reference)
+will be passed to the filter to be changed or converted into an object,
+or whatever you wish.
+
+Returns a new L<Parse::CSV> object, or throws an exception (dies) on error.
+
+=cut
+
+sub new {
+ my $class = shift;
+ my $self = bless { @_,
+ row => 0,
+ errstr => '',
+ }, $class;
+
+ # Do we have a file name
+ if ( exists $self->{file} ) {
+ unless ( _STRING($self->{file}) ) {
+ Carp::croak("Parse::CSV file param is not a string");
+ }
+ unless ( -f $self->{file} and -r _ ) {
+ Carp::croak("Parse::CSV file '$self->{file}' does not exist");
+ }
+ $self->{handle} = IO::File->new();
+ unless ( $self->{handle}->open($self->{file}) ) {
+ Carp::croak("Parse::CSV file '$self->{file}' failed to load: $!");
+ }
+ }
+
+ # Do we have a file handle
+ if ( exists $self->{handle} ) {
+ unless ( _HANDLE($self->{handle}) ) {
+ Carp::croak("Parse::CSV handle param is not an IO handle");
+ }
+ } else {
+ Carp::croak("Parse::CSV not provided a file or handle param");
+ }
+
+ # Seperate the Text::CSV attributes
+ unless ( _HASH0($self->{csv_attr}) ) {
+ $self->{csv_attr} = {};
+ foreach ( qw{quote_char eol escape_char sep_char binary always_quote} ) {
+ next unless exists $self->{$_};
+ $self->{csv_attr}->{$_} = delete $self->{$_};
+ }
+ }
+
+ # Create the parser
+ $self->{csv_xs} = Text::CSV_XS->new( $self->{csv_attr} );
+ unless ( $self->{csv_xs} ) {
+ Carp::croak("Failed to create Text::CSV_XS parser");
+ }
+
+ # Handle automatic fields
+ if ( _STRING($self->{fields}) and lc($self->{fields}) eq 'auto' ) {
+ # Grab the first line
+ my $line = $self->_getline;
+ unless ( defined $line ) {
+ Carp::croak("Failed to get header line from CSV");
+ }
+
+ # Parse the line into columns
+ unless ( $self->{csv_xs}->parse($line) ) {
+ Carp::croak(
+ "Failed to parse header line from CSV: "
+ . $self->{csv_xs}->error_input
+ );
+ }
+
+ # Turn the array ref into a hash if needed
+ my @cols = $self->{csv_xs}->fields;
+ $self->{fields} = \@cols;
+ }
+
+ # Check fields
+ if ( exists $self->{fields} and ! _ARRAY($self->{fields}) ) {
+ Carp::croak("Parse::CSV fields param is not an array reference of strings");
+ }
+
+ # Check filter
+ if ( exists $self->{filter} and ! _CODELIKE($self->{filter}) ) {
+ Carp::croak("Parse::CSV filter param is not callable");
+ }
+
+ $self;
+}
+
+
+
+
+
+#####################################################################
+# Main Methods
+
+=pod
+
+=head2 fetch
+
+Once a L<Parse::CSV> object has been created, the C<fetch> method is
+used to parse and return the next value from the CSV file.
+
+Returns an C<ARRAY>, C<HASH> or the output of the filter, based on the
+configuration of the object, or C<undef> in a variety of situations.
+
+Returning C<undef> means either some part of the parsing and filtering
+process has resulted in an error, B<or> that the end of file has been
+reached.
+
+On receiving C<undef>, you should the C<errstr> method. If it is a null
+string you have reached the end of file. Otherwise the error message will
+be returned. Thus, the basic usage of L<Parse::CSV> will look like the
+following.
+
+ my $parser = Parse::CSV->new(
+ file => 'file.csv',
+ );
+ while ( my $value = $parser->fetch ) {
+ # Do something...
+ }
+ if ( $parser->errstr ) {
+ # Handle errors...
+ }
+
+=cut
+
+sub fetch {
+ my $self = shift;
+
+ # The filter can skip rows,
+ # iterate till we get something.
+ while ( defined(my $line = $self->_getline) ) {
+ # Parse the line into columns
+ unless ( $self->{csv_xs}->parse($line) ) {
+ $self->{errstr} = "Failed to parse row $self->{row}";
+ return undef;
+ }
+
+ # Turn the array ref into a hash if needed
+ my $rv = undef;
+ my $f = $self->{fields};
+ my @cols = $self->{csv_xs}->fields;
+ if ( $f ) {
+ $rv = {};
+ foreach ( 0 .. $#$f ) {
+ $rv->{ $f->[$_] } = $cols[$_];
+ }
+ } else {
+ $rv = \@cols;
+ }
+
+ # Just return for simple uses
+ return $rv unless $self->{filter};
+
+ # Filter if needed
+ local $_ = $rv;
+ $rv = eval { $self->{filter}->() };
+ if ( $@ ) {
+ # Handle filter errors
+ $self->{errstr} = "Filter error: $@";
+ $self->{errstr} =~ s/^(.+)at line.+$/$1/;
+ return undef;
+ }
+
+ # Filter returns undef to drop a record
+ next unless defined $rv;
+
+ # We have a good record, return it
+ return $rv;
+ }
+
+ return undef;
+}
+
+sub _getline {
+ my $self = shift;
+ $self->{errstr} = '';
+
+ # Fetch the next file line
+ my $handle = $self->{handle};
+ my $line = <$handle>;
+ unless ( defined $line ) {
+ $self->{errstr} = $handle->eof ? '' : $!;
+ return undef;
+ }
+
+ # Parse the line into columns
+ $self->{row}++;
+ return $line;
+}
+
+=pod
+
+=head2 row
+
+The C<row> method returns the current row of the CSV file.
+
+This is a one-based count, so when you first create the parser,
+the value of C<row> will be zero (unless you are using
+C<fields => 'auto'> in which case it will be 1).
+
+=cut
+
+sub row {
+ $_[0]->{row};
+}
+
+=pod
+
+=head2 combine
+
+ $status = $csv->combine(@columns);
+
+The C<combine> method is provided as a convenience, and is passed through
+to the underlying L<Text::CSV_XS> object.
+
+=cut
+
+sub combine {
+ shift->combine(@_);
+}
+
+=pod
+
+=head2 string
+
+ $line = $cvs->string;
+
+The C<string> method is provided as a convenience, and is passed through
+to the underlying L<Text::CSV_XS> object.
+
+=cut
+
+sub string {
+ shift->string(@_);
+}
+
+=pod
+
+=head2 print
+
+ $status = $cvs->print($io, $columns);
+
+The C<print> method is provided as a convenience, and is passed through
+to the underlying L<Text::CSV_XS> object.
+
+=cut
+
+sub print {
+ shift->print(@_);
+}
+
+=pod
+
+=head2 errstr
+
+On error, the C<errstr> method returns the error that occured.
+
+If the last action was NOT an error, returns the null string C<''>.
+
+=cut
+
+sub errstr {
+ $_[0]->{errstr};
+}
+
+1;
+
+=pod
+
+=head1 SUPPORT
+
+Bugs should be always be reported via the CPAN bug tracker at
+
+L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Parse-CSV>
+
+For other issues, or commercial enhancement or support, contact the author.
+
+=head1 AUTHORS
+
+Adam Kennedy E<lt>adamk@cpan.orgE<gt>
+
+=head1 SEE ALSO
+
+L<Text::CSV_XS>, L<http://ali.as/>
+
+=head1 COPYRIGHT
+
+Copyright 2006 Adam Kennedy.
+
+This program is free software; you can redistribute
+it and/or modify it under the same terms as Perl itself.
+
+The full text of the license can be found in the
+LICENSE file included with this module.
+
+=cut