File Coverage

blib/lib/CouchDB/View/Server.pm
Criterion Covered Total %
statement 39 51 76.4
branch 6 18 33.3
condition 3 5 60.0
subroutine 11 14 78.5
pod 3 10 30.0
total 62 98 63.2


line stmt bran cond sub pod time code
1 1     1   54226 use strict;
  1         2  
  1         40  
2 1     1   5 use warnings;
  1         2  
  1         47  
3              
4             package CouchDB::View::Server;
5              
6 1     1   1363 use JSON::XS;
  1         9730  
  1         73  
7 1     1   1457 use IO::Handle;
  1         10675  
  1         830  
8              
9             my $j = JSON::XS->new;
10              
11             {
12             our @d;
13 1     1 0 4 sub dmap { push @d, [@_] }
14             }
15              
16 1     1 0 28 sub new { bless $_[1] => $_[0] }
17              
18 0 0   0 0 0 sub in { @_ > 1 ? ($_[0]->{in} = $_[1]) : $_[0]->{in} }
19 3 50   3 0 70 sub out { @_ > 1 ? ($_[0]->{out} = $_[1]) : $_[0]->{out} }
20 1 50   1 0 15 sub funs { @_ > 1 ? ($_[0]->{funs} = $_[1]) : $_[0]->{funs} }
21              
22             my %fun_cache;
23              
24             sub run {
25 0     0 0 0 my $self = shift;
26              
27 0 0       0 $self = $self->new if not ref $self; # autovivify
28              
29 0 0       0 $self->in or $self->in (IO::Handle->new_from_fd(\*STDIN, 'r'));
30 0 0       0 $self->out or $self->out(IO::Handle->new_from_fd(\*STDOUT, 'w'));
31              
32 0         0 $self->out->autoflush(1);
33              
34 0         0 while (defined(my $line = $self->in->getline)) {
35 0         0 $self->process($line);
36             }
37             }
38              
39             sub process {
40 3     3 0 23547 my ($self, $line) = @_;
41 3         12 chomp($line);
42 3         36 my $input = $j->decode($line);
43 3         12 my ($cmd, @args) = @$input;
44 3         21 $self->can($cmd)->($self, @args);
45             }
46              
47             sub reset {
48 0     0 1 0 my ($self) = @_;
49 0         0 delete $self->{funs};
50 0         0 $self->out->print("true\n");
51             }
52              
53             sub add_fun {
54 2     2 1 4 my ($self, $code) = @_;
55 2   66     139 my $sub = $fun_cache{$code} ||= eval $code;
56 2 100       10 if (my $e = $@) {
57 1         4 $self->out->print(
58             $j->encode({
59             error => {
60             id => "map_compilation_error",
61             reason => $e,
62             },
63             }), "\n",
64             );
65             } else {
66 1   50     2 push @{ $self->{funs} ||= [] }, $sub;
  1         12  
67 1         6 $self->out->print("true\n");
68             }
69             }
70              
71             sub map_doc {
72 1     1 1 2 my ($self, $doc) = @_;
73 1         3 my @result;
74 1 50       2 for my $sub (@{ $self->funs || [] }) {
  1         5  
75 1         3 our @d;
76 1         2 local @d;
77 1         2 eval { $sub->($doc) };
  1         39  
78             # we don't have any concept of 'fatal' yet
79 1 50       5 if (my $e = $@) {
80 0         0 warn $e;
81             } else {
82 1         5 push @result, [@d];
83             }
84             }
85              
86 1         6 $self->out->print($j->utf8->encode(\@result), "\n");
87             }
88              
89              
90             1;
91             __END__