File Coverage

blib/lib/Net/PSYC/MMP/State.pm
Criterion Covered Total %
statement 6 30 20.0
branch 0 16 0.0
condition n/a
subroutine 2 7 28.5
pod 0 5 0.0
total 8 58 13.7


line stmt bran cond sub pod time code
1             package Net::PSYC::MMP::State;
2              
3 1     1   5742 use Storable qw(dclone);
  1         17267  
  1         88  
4 1     1   13 use strict;
  1         2  
  1         629  
5              
6             sub outstate {
7 0     0 0   my $self = shift;
8 0           my ($mod, $var, $val) = @_;
9              
10 0 0         return 1 if ($mod eq ':');
11            
12 0 0         if ($mod eq '=') {
    0          
    0          
13 0           $self->{'state'}->{$var} = $val;
14 0           return 1;
15             } elsif ($mod eq '+') {
16 0           Net::PSYC::_augment($self->{'state'}, $var, $val);
17 0           return 1;
18             } elsif ($mod eq '-') {
19 0 0         return 1 if (Net::PSYC::_diminish($self->{'state'}, $var, $val));
20             }
21 0           return 0;
22             }
23              
24             sub state {
25             {}
26 0     0 0   }
27              
28             sub assign {
29 0     0 0   my $self = shift;
30 0           my ($var, $val) = @_;
31              
32 0 0         unless ($val) {
33 0           delete $self->{'vars'}->{$var};
34 0           return 1;
35             }
36 0           $self->{'vars'}->{$var} = $val;
37 0 0         $self->negotiate($val) if ($var eq '_using_modules');
38             }
39              
40             sub augment {
41 0     0 0   my $self = shift;
42 0           my ($var, $val) = @_;
43 0           Net::PSYC::_augment($self->{'vars'}, @_);
44            
45 0 0         $self->negotiate($val) if ($var eq '_using_modules');
46             }
47              
48             sub diminish {
49 0     0 0   my $self = shift;
50 0           Net::PSYC::_diminish($self->{'vars'}, @_);
51             }
52              
53             =old
54             sub new {
55             my $class = shift;
56             my $obj = shift;
57             my $self = {
58             'state' => {},
59             'vars' => {},
60             'state_temp' => {},
61             'connection' => $obj,
62             };
63             return bless $self, $class;
64             }
65              
66             sub init {
67             my $self = shift;
68             # do state after encoding and stuff has been done, does not make a
69             # difference really
70             $self->{'connection'}->hook('send', $self, -10);
71             $self->{'connection'}->hook('sent', $self);
72             $self->{'connection'}->hook('receive', $self, 10);
73             # do encoding-stuff _after_ state. this is essential if _encoding
74             # ist stateful.
75             return 1;
76             }
77              
78             sub send {
79             my $self = shift;
80             my ($vars, $data) = @_;
81             # use Data::Dumper;
82             # print STDERR Dumper(@_);
83             # the current behaviour is to _set every var that
84             # has not changed in 3 packages..
85             my $state = $self->{'state'};
86             my $state_temp = {};
87             my $newvars = {};
88              
89             # to bypass automatic state.. use ':'
90             foreach (keys %$vars) {
91              
92             next if (/^:_/);
93             if (/^=_/) {
94             $newvars->{$_} = $vars->{$_};
95             $state_temp->{substr($_, 1)} = [0, $vars->{$_}];
96             next;
97             }
98             if (/^\+_/) {
99             my $key = substr($_, 1);
100             $newvars->{$_} = $vars->{$_};
101             if (exists $state->{$key}) {
102             unless (ref $state->{$key}->[1] eq 'ARRAY') {
103             $state_temp->{$key}->[1] = [ $state->{$key}->[1] ];
104             }
105             push(@{$state_temp->{$key}->[1]}, $vars->{$_});
106             } else {
107             $state_temp->{$key}->[1] = [ $vars->{$_} ];
108             }
109             $state_temp->{$key}->[0] = 0; # we assume it to be consistent
110             next;
111             }
112             if (/^-_/) {
113             my $key = substr($_, 1);
114             $newvars->{$_} = $vars->{$_};
115             if (exists $state->{$key}) {
116             if (ref $state->{$key}->[1] eq 'ARRAY') {
117             $state_temp->{$key}->[1] = grep { $_ eq $vars->{$_} }
118             @{$state->{$key}->[1]};
119             } else {
120             if ($state->{$key}->[1] eq $vars->{$_}) {
121             $state_temp->{$key}->[0] = -1;
122             }
123             }
124             } else {
125             # WOU?
126             }
127             $state_temp->{$key}->[0] = 0; # we assume it to be consistent
128             next;
129             }
130            
131             if (!exists $state->{$_}) {
132             $state_temp->{$_} = [1, $vars->{$_}];
133             $newvars->{$_} = $vars->{$_};
134             next;
135             }
136             if ($state->{$_}->[1] ne $vars->{$_}) { # var has changed
137             if ($state->{$_}->[0] == 3) { # unset var
138             $state_temp->{$_} = [1, $vars->{$_}];
139             $newvars->{"=$_"} = '';
140             } elsif ($state->{$_}->[0] > 1) { # decrease counter
141             $state_temp->{$_} = [ $state->{$_}->[0] - 1, $state->{$_}->[1]];
142             } elsif ($state->{$_}->[0] != 0) { # nothing set..
143             $state_temp->{$_} = [1, $vars->{$_}];
144             }
145             $newvars->{$_} = $vars->{$_};
146             next;
147             }
148             if ($state->{$_}->[1] eq $vars->{$_}) {
149             if ($state->{$_}->[0] == 10 || $state->{$_}->[0] == 0) {
150             # is set anyway
151             next;
152             } elsif ($state->{$_}->[0] == 2) {
153             $newvars->{"=$_"} = $vars->{$_};
154             } elsif ($state->{$_}->[0] < 2) {
155             $newvars->{$_} = $vars->{$_};
156             }
157             $state_temp->{$_} = [$state->{$_}->[0] + 1, $state->{$_}->[1]];
158             }
159             }
160              
161             foreach (keys %$state) {
162             next if (exists $newvars->{$_} || exists $vars->{$_});
163            
164             if ($state->{$_}->[0] == 3) { # unset var
165             $newvars->{"=$_"} = '';
166             $state_temp->{$_} = [ 2, $state->{$_}->[1]];
167             next;
168             }
169             $state_temp->{$_} = [ $state->{$_}->[0] - 1, $state->{$_}->[1]]
170             if ($state->{$_}->[0] != 0);
171             $newvars->{$_} = '' if ($state->{$_}->[0] > 3);
172             }
173            
174             $self->{'state_temp'} = $state_temp;
175             %$vars = %$newvars;
176             return 1;
177             }
178              
179             sub sent {
180             my $self = shift;
181             my ($vars, $data) = @_;
182            
183             foreach (keys %{$self->{'state_temp'}}) {
184             if ($self->{'state_temp'}->{$_}->[0] == -1) {
185             delete $self->{'state'}->{$_};
186             next;
187             }
188             $self->{'state'}->{$_} = $self->{'state_temp'}->{$_};
189             }
190             return 1;
191             }
192              
193             sub receive {
194             my $self = shift;
195             my ($vars, $data) = @_;
196            
197             foreach (keys %{$self->{'vars'}}) {
198             unless (exists $vars->{$_}) {
199             # print "used assigned var $_ ($self->{'vars'}->{$_})!\n";
200             $vars->{$_} = $self->{'vars'}->{$_};
201             }
202             }
203              
204             foreach (keys %$vars) {
205             if (/^_/) {
206             delete $vars->{$_} if ($vars->{$_} eq '');
207             next;
208             }
209             my $key = substr($_, 1);
210             if (/^=_/) {
211             # print "assigned $key!\n";
212             if ($vars->{$_} eq '') {
213             delete $self->{'vars'}->{$key};
214             delete $vars->{$_};
215             next;
216             }
217             $self->{'vars'}->{$key} = (ref $vars->{$_})
218             ? dclone($vars->{$_}) : $vars->{$_};
219              
220             $vars->{$key} = delete $vars->{$_};
221             next;
222             }
223             if (/^\+_/) {
224             if (!exists $self->{'vars'}->{$key}) {
225             $self->{'vars'}->{$key} = [ delete $vars->{$_} ];
226             next;
227             }
228             if (ref $self->{'vars'}->{$key} eq 'ARRAY') {
229             push(@{$self->{'vars'}->{$key}}, $vars->{$_});
230             } else {
231             $self->{'vars'}->{$key} = [ $self->{'vars'}->{$key},
232             $vars->{$_} ];
233             }
234             delete $vars->{$_};
235             next;
236             }
237             if (/^-_/) {
238             if (!exists $self->{'vars'}->{$key}) {
239              
240             } elsif (!ref $self->{'vars'}->{$key}) {
241             delete $self->{'vars'}->{$key}
242             if ($self->{'vars'}->{$key} eq $vars->{$_});
243             } elsif (ref $self->{'vars'}->{$key} eq 'ARRAY') {
244             my $value = $vars->{$key};
245             @{$self->{'vars'}->{$key}} =
246             grep {$_ ne $value } @{$self->{'vars'}->{$key}};
247             }
248             delete $vars->{$_};
249             next;
250             }
251             }
252             return 1;
253             }
254             =cut
255             1;