File Coverage

blib/lib/Metabrik/String/Csv.pm
Criterion Covered Total %
statement 9 73 12.3
branch 0 24 0.0
condition n/a
subroutine 3 6 50.0
pod 1 3 33.3
total 13 106 12.2


line stmt bran cond sub pod time code
1             #
2             # $Id$
3             #
4             # string::csv Brik
5             #
6             package Metabrik::String::Csv;
7 1     1   793 use strict;
  1         2  
  1         29  
8 1     1   5 use warnings;
  1         2  
  1         27  
9              
10 1     1   5 use base qw(Metabrik);
  1         2  
  1         878  
11              
12             sub brik_properties {
13             return {
14 0     0 1   revision => '$Revision$',
15             tags => [ qw(unstable) ],
16             author => 'GomoR ',
17             license => 'http://opensource.org/licenses/BSD-3-Clause',
18             attributes => {
19             first_line_is_header => [ qw(0|1) ],
20             separator => [ qw(character) ],
21             header => [ qw($column_header_list) ],
22             encoding => [ qw(utf8|ascii) ],
23             escape => [ qw(character) ],
24             quote => [ qw(character) ],
25             },
26             attributes_default => {
27             first_line_is_header => 0,
28             header => [ ],
29             separator => ';',
30             encoding => 'utf8',
31             escape => '"',
32             quote => '"',
33             },
34             commands => {
35             encode => [ qw($data) ],
36             decode => [ qw($data) ],
37             },
38             require_modules => {
39             'IO::Scalar' => [ ],
40             'Text::CSV_XS' => [ ],
41             },
42             };
43             }
44              
45             sub encode {
46 0     0 0   my $self = shift;
47 0           my ($data) = @_;
48              
49 0 0         $self->brik_help_run_undef_arg('encode', $data) or return;
50             # We only handle array of hashes format (aoh) for writing
51 0 0         $self->brik_help_run_invalid_arg('encode', $data, 'ARRAY') or return;
52 0 0         $self->brik_help_run_empty_array_arg('encode', $data, 'ARRAY') or return;
53              
54 0 0         if (ref($data->[0]) ne 'HASH') {
55 0           return $self->log->error("encode: csv structure does not contain HASHes");
56             }
57              
58 0           my $output = '';
59 0           my $fd = IO::Scalar->new(\$output);
60              
61 0           my $header_written = 0;
62 0           my %order = ();
63 0           for my $this (@$data) {
64 0 0         if (! $header_written) {
65 0           my $idx = 0;
66 0           for my $k (sort { $a cmp $b } keys %$this) {
  0            
67 0           $order{$k} = $idx;
68 0           $idx++;
69             }
70 0           my @header = sort { $a cmp $b } keys %$this;
  0            
71 0           my $string = join($self->separator, @header)."\n";
72 0           print $fd $string;
73 0           $header_written++;
74             }
75              
76 0           my @fields = ();
77 0           for my $key (sort { $a cmp $b } keys %$this) {
  0            
78 0           $fields[$order{$key}] = $this->{$key};
79             }
80              
81 0           for (@fields) {
82 0 0         if (! defined($_)) {
83 0           $_ = '';
84             }
85             }
86              
87 0           my $string = join($self->separator, @fields)."\n";
88 0           print $fd $string;
89             }
90              
91 0           $fd->close;
92              
93 0 0         if (! length($output)) {
94 0           return $self->log->error("encode: nothing to encode");
95             }
96              
97 0           return $output;
98             }
99              
100             sub decode {
101 0     0 0   my $self = shift;
102 0           my ($data) = @_;
103              
104 0 0         $self->brik_help_run_undef_arg('decode', $data) or return;
105              
106 0 0         my $csv = Text::CSV_XS->new({
107             binary => 1,
108             sep_char => $self->separator,
109             allow_loose_quotes => 1,
110             allow_loose_escapes => 1,
111             escape_char => $self->escape,
112             quote_char => $self->quote,
113             }) or return $self->log->error("decode: Text::CSV_XS new failed");
114              
115 0           my $fd = IO::Scalar->new(\$data);
116              
117 0           my $sep = $self->separator;
118 0           my $headers;
119             my $count;
120 0           my $first_line = 1;
121 0           my @rows = ();
122 0           while (my $row = $csv->getline($fd)) {
123 0 0         if ($self->first_line_is_header) {
124 0 0         if ($first_line) { # This is first line
125 0           $headers = $row;
126 0           $count = scalar @$row - 1;
127 0           $first_line = 0;
128 0           $self->header($headers);
129 0           next;
130             }
131              
132 0           my $h;
133 0           for (0..$count) {
134 0           $h->{$headers->[$_]} = $row->[$_];
135             }
136 0           push @rows, $h;
137             }
138             else {
139 0           push @rows, $row;
140             }
141             }
142              
143 0 0         if (! $csv->eof) {
144 0           my $error_str = "".$csv->error_diag();
145 0           $self->log->error("decode: incomplete: error [$error_str]");
146 0           return \@rows;
147             }
148              
149 0           return \@rows;
150             }
151              
152             1;
153              
154             __END__