File Coverage

blib/lib/PFIX/Message.pm
Criterion Covered Total %
statement 128 150 85.3
branch 42 62 67.7
condition 8 12 66.6
subroutine 16 18 88.8
pod 0 10 0.0
total 194 252 76.9


line stmt bran cond sub pod time code
1             package PFIX::Message;
2              
3 2     2   2326 use warnings;
  2         4  
  2         61  
4 2     2   9 use strict;
  2         2  
  2         54  
5              
6 2     2   524 use PFIX::Dictionary;
  2         5  
  2         38  
7              
8 2     2   10 use Data::Dumper;
  2         2  
  2         3213  
9              
10             sub new {
11 1     1 0 758 my ( $proto, %vars ) = @_;
12              
13 1   33     549 my $class = ref($proto) || $proto;
14 1         2 my $self = {};
15 1         3 bless( $self, $class );
16              
17 1 50       4 if ( defined $vars{version} ) {
18 0         0 PFIX::Dictionary::load( $vars{version} );
19             }
20             else {
21 1         4 PFIX::Dictionary::load('FIX44');
22             }
23 1 50       6 if ( defined $vars{dd} ) {
24 0         0 $self->{_dd} = $vars{dd};
25             }
26             else {
27 1         10 $self->{_dd} = PFIX::Dictionary->new();
28             }
29              
30 1         7 return $self;
31             }
32              
33             sub _parseFixArray($$$$$$);
34              
35             sub _parseFixArray($$$$$$) {
36 27     27   53 my ( $self, $arr, $msgType, $gName, $iField, $fields ) = @_;
37              
38 27         38 my $fixDico = $self->{_dd};
39 27         34 my $n = scalar(@$fields);
40 27         28 my $i = $iField;
41 27         73 while ( $i < $n ) {
42 246         329 my $field = $fields->[$i];
43 246         1179 my ( $k, $v ) = ( $field =~ /^([^=]+)=(.*)$/ );
44 246 100       575 if ( defined $arr->{$k} ) {
45 9 50       29 return $i if defined $gName;
46 0         0 warn("Field $k is already in hash!");
47             }
48 237 100       373 if ( defined $gName ) {
49 45 100       121 return $i if !$fixDico->isFieldInGroup( $msgType, $gName, $k );
50             }
51 228         448 $arr->{$k} = $v;
52 228 100       502 if ( $k == 8 ) {
    100          
53              
54             #do nothing
55             }
56             elsif ( $k == 35 ) {
57 9         11 $msgType = $v;
58             }
59             else {
60 210         520 my $fieldName = $fixDico->getFieldName($k);
61 210 100       634 if ( !defined $fieldName ) {
    100          
62 3         475 warn("Did not find field $k in dictionary");
63             }
64             elsif ( $fixDico->isGroup($k) ) {
65 9         17 my @elems;
66 9         12 ++$i;
67 9         42 for my $j ( 1 .. $v ) {
68 18         22 my %newArr;
69 18         55 $i = _parseFixArray( $self, \%newArr, $msgType, $k, $i, $fields );
70 18         50 push( @elems, \%newArr );
71             }
72 9         23 $arr->{$k} = \@elems;
73 9         25 --$i;
74             }
75             }
76 228         582 ++$i;
77             }
78             }
79              
80             sub fromString($$) {
81 9     9 0 2991 my ( $self, $s ) = @_;
82              
83 9 50       25 return if !defined $s;
84 9         13 my %arr;
85 9         103 my @fields = split( "\001", $s );
86 9         24 my $n = scalar(@fields) - 1;
87 9         36 _parseFixArray( $self, \%arr, undef, undef, 0, \@fields );
88              
89 9         20 $self->{_AMSG} = \%arr;
90 9         143 $self->{_SMSG} = $s;
91             }
92              
93             sub resetString($) {
94 4     4 0 12 my $self = shift;
95 4         12 $self->{_SMSG} = undef;
96             }
97              
98             sub __toString($$) {
99 0     0   0 my ( $self, $m, $order ) = @_;
100 0         0 my %newHash;
101 0         0 while ( my ( $k, $v ) = each(%$m) ) {
102 0         0 my $o = $order->{$k};
103 0         0 print "$k ($o) \n";
104 0 0       0 if ( ref($v) eq 'ARRAY' ) {
105 0         0 my @newO;
106 0         0 for my $g (@$v) {
107 0         0 my %newH = $self->_toString( $g, $order );
108 0         0 push( @newO, \%newH );
109             }
110 0         0 $newHash{$o} = { $k => \@newO };
111             }
112             else {
113 0         0 $newHash{$o} = { $k => $v };
114             }
115             }
116 0         0 %newHash;
117             }
118 656     656   680 sub _numeric { $a <=> $b }
119              
120             sub _toString($$) {
121 24     24   52 my ( $self, $m, $order ) = @_;
122 24         23 my %newHash;
123 24         115 while ( my ( $k, $v ) = each(%$m) ) {
124 214         284 my $o = $order->{$k};
125 214 100       353 if ( !defined $o ) {
126 15         30 $o = 1000000 + $k;
127             }
128 214 100       321 if ( ref($v) eq 'ARRAY' ) {
129 8         45 my @newArr;
130 8         19 for my $g (@$v) {
131 16         42 my $str = $self->_toString( $g, $order );
132 16         41 push( @newArr, $str );
133             }
134 8         49 $newHash{$o} = { $k => \@newArr };
135             }
136             else {
137 206         1125 $newHash{$o} = { $k => $v };
138             }
139             }
140 24         33 my $retStr;
141 24         140 for my $k ( sort _numeric keys %newHash ) {
142 214         278 my $v = $newHash{$k};
143 214         503 my ( $tag, $val ) = %$v;
144 214 100 100     1232 next if ( $tag == 8 || $tag == 9 || $tag == 10 );
      100        
145 190 100       317 if ( ref($val) eq 'ARRAY' ) {
146 8         20 $retStr .= "$tag=" . scalar(@$val) . "\001";
147 8         14 for my $e (@$val) {
148 16         37 $retStr .= $e;
149             }
150             }
151             else {
152 182         411 $retStr .= "$tag=$val\001";
153             }
154             }
155 24         184 $retStr;
156             }
157              
158             sub toString($) {
159 8     8 0 13 my $self = shift;
160              
161 8 50       21 return $self->{_SMSG} if defined $self->{_SMSG};
162              
163 8         20 my $msgtype = $self->getField('MsgType');
164 8         30 my %order = $self->{_dd}->getMessageOrder($msgtype);
165 8         192 my $str = $self->_toString( $self->{_AMSG}, \%order );
166 8         20 my $l = length($str);
167 8         33 $self->setField( 9, $l ); # BodyLength
168 8         28 $str = "8=" . $self->getField(8) . "\0019=" . $self->getField(9) . "\001" . $str;
169              
170             # calculate checksum
171 8         75 my $sum = unpack( "%8C*", $str ) % 256;
172 8         61 $self->setField( 10, sprintf( "%03d", $sum ) );
173 8         20 $str .= "10=" . $self->getField(10) . "\001";
174 8         17 $self->{_SMSG} = $str;
175              
176 8         188 $str;
177             }
178              
179             sub toPrint($) {
180 8     8 0 26 my $self = shift;
181 8         28 my $ret;
182 8 50       29 if ( ref($self) eq 'PFIX::Message' ) {
183 8         23 $self->toString();
184 8         19 $ret = $self->{_SMSG};
185             }
186             else {
187 0         0 $ret = $self;
188             }
189 8         105 $ret =~ s/\001/\|/g;
190 8         109 $ret;
191             }
192              
193             sub getField($$) {
194 33     33 0 54 my ( $self, $f ) = @_;
195 33 100       139 $f = $self->{_dd}->getFieldNumber($f) if ( $f !~ /^\d+$/ );
196 33 50       55 return if !defined $f;
197              
198 33         62 my $v = $self->{_AMSG}->{$f};
199 33 100       69 if ( ref($v) eq '' ) {
200 32         123 return $v;
201             }
202 1 50       4 if ( ref($v) eq 'ARRAY' ) {
203 1         5 return scalar(@$v);
204             }
205              
206 0         0 undef;
207             }
208              
209             sub setField($$$) {
210 18     18 0 42 my ( $self, $f, $v ) = @_;
211 18         68 $f = $self->{_dd}->getFieldNumber($f);
212 18 50       46 return if !defined $f;
213              
214 18         37 $self->{_AMSG}->{$f} = $v;
215 18         35 $self->{_SMSG} = undef;
216             }
217              
218             sub delField($$) {
219 2     2 0 4 my ( $self, $f ) = @_;
220              
221 2         8 $f = $self->{_dd}->getFieldNumber($f);
222 2 50       7 return if !defined $f;
223              
224 2 50       11 delete( $self->{_AMSG}->{$f} ) if defined( $self->{_AMSG}->{$f} );
225 2         6 $self->{_SMSG} = undef;
226             }
227              
228             sub getFloat($$) {
229 0     0 0 0 my ( $self, $f ) = @_;
230 0         0 my $v = $self->getField($f);
231 0 0       0 return defined $v ? $v * 1.0 : 0.0;
232             }
233              
234             sub getFieldInGroup($$$$) {
235 2     2 0 4 my ( $self, $g, $n, $f ) = @_;
236 2 50 33     25 $g = $self->{_dd}->getFieldNumber($g) if ( defined $self->{_dd} && $g !~ /^\d+$/ );
237 2 50       5 return if !defined $g;
238              
239 2         5 my $v = $self->{_AMSG}->{$g};
240 2 50       5 if ( ref($v) eq 'ARRAY' ) {
241 2 50       9 $f = $self->{_dd}->getFieldNumber($f) if ( $f !~ /^\d+$/ );
242 2 50       5 return if !defined $f;
243 2         10 return $v->[$n]->{$f};
244             }
245              
246 0           undef;
247             }
248              
249             # the end!
250             1;