File Coverage

blib/lib/BACnet/DataTypes/SequenceValue.pm
Criterion Covered Total %
statement 65 83 78.3
branch 22 30 73.3
condition 7 12 58.3
subroutine 8 8 100.0
pod 0 2 0.0
total 102 135 75.5


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             package BACnet::DataTypes::SequenceValue;
4              
5 27     27   157 use warnings;
  27         47  
  27         1458  
6 27     27   122 use strict;
  27         44  
  27         587  
7              
8 27     27   109 use BACnet::DataTypes::Utils;
  27         41  
  27         3154  
9              
10             require BACnet::DataTypes::BitString;
11             require BACnet::DataTypes::Bool;
12             require BACnet::DataTypes::Date;
13             require BACnet::DataTypes::Double;
14             require BACnet::DataTypes::Enum;
15             require BACnet::DataTypes::Int;
16             require BACnet::DataTypes::Null;
17             require BACnet::DataTypes::ObjectIdentifier;
18             require BACnet::DataTypes::OctetString;
19             require BACnet::DataTypes::Real;
20             require BACnet::DataTypes::SequenceOfValues;
21             require BACnet::DataTypes::Time;
22             require BACnet::DataTypes::UnsignedInt;
23             require BACnet::DataTypes::CharString;
24             require BACnet::DataTypes::Bone;
25              
26 27     27   15190 use BACnet::DataTypes::Enums::PropertyIdentifier;
  27         101  
  27         1728  
27              
28 27     27   189 use parent 'BACnet::DataTypes::DataType';
  27         50  
  27         140  
29              
30             use constant {
31 27         22507 DEFAULT_SUBSTITUTION_NAME => "default",
32             DEFAULT_SUBSTITUTION =>
33             $BACnet::DataTypes::Enums::PropertyIdentifier::prop_type_type,
34 27     27   2149 };
  27         48  
35              
36             sub construct {
37 38     38 0 159 my ( $class, $values, $modified_tag ) = @_;
38              
39 38         149 my $self = {
40             data => '',
41             val => {},
42             };
43              
44 38 100       164 if ( defined $modified_tag ) {
45 11         32 $self->{data} .= BACnet::DataTypes::Utils::_make_head( $modified_tag, 1,
46             BACnet::DataTypes::Utils::OPENING_LVT, 1 );
47             }
48              
49 38         91 foreach my $name_value (@$values) {
50 82         153 my ( $name, $value ) = @$name_value;
51 82         340 $self->{data} .= $value->data();
52 82         174 %{ $self->{val} } = ( %{ $self->{val} }, $name => $value );
  82         335  
  82         168  
53             }
54 38 100       181 if ( defined $modified_tag ) {
55 11         40 $self->{data} .= BACnet::DataTypes::Utils::_make_head( $modified_tag, 1,
56             BACnet::DataTypes::Utils::CLOSING_LVT, 1 );
57             }
58              
59 38         205 return bless $self, $class;
60             }
61              
62             # TAG => (NAME, DATA TYPE, INNER SKELETON)
63             # 10 => (sth, BACnet::DataTypes::SequenceValue, { 10 => (temp, BACnet::DataTypes::Int, undef) })
64             #
65             #
66              
67             sub parse {
68 48     48 0 164 my ( $class, $data_in, $skeleton ) = @_;
69              
70 48         207 my $self = bless { data => '', val => {} }, $class;
71              
72 48 100       218 if ( ( length $data_in ) == 0 ) {
73 4         19 return $self;
74             }
75              
76 44         77 my $head_index = 0;
77 44         74 my $context_tag = undef;
78 44         64 my $end_tag_len = 0;
79              
80 44 100       152 if ( BACnet::DataTypes::Utils::_is_context_sequence($data_in) ) {
81 15         65 $context_tag = BACnet::DataTypes::Utils::_get_head_tag($data_in);
82              
83 15 50       35 if ( $context_tag == -1 ) {
84             $self->{error} =
85 0         0 "SequenceValue: opening context lvt tag parse error";
86 0         0 return $self;
87             }
88 15         36 $head_index += BACnet::DataTypes::Utils::_get_head_length($data_in);
89             }
90              
91 44         110 for my $bone (@$skeleton) {
92 113 100       250 if ( length($data_in) <= $head_index ) {
93 1         3 last;
94             }
95              
96 112 50 66     333 if (
97             BACnet::DataTypes::Utils::_is_end_of_context_sequence(
98             substr( $data_in, $head_index )
99             )
100             && ( defined $context_tag )
101             )
102             {
103 0 0       0 if (
104             $context_tag != BACnet::DataTypes::Utils::_get_head_tag(
105             substr( $data_in, $head_index )
106             )
107             )
108             {
109             $self->{error} =
110 0         0 "SequenceValue: closing context lvt tag parse error";
111 0         0 return $self;
112             }
113             else {
114 0         0 $self->{data} = substr( $data_in, 0,
115             $head_index +
116             BACnet::DataTypes::Utils::_get_head_length($data_in) );
117 0         0 return $self;
118             }
119             }
120              
121 112         348 my $dt_tag = BACnet::DataTypes::Utils::_get_head_tag(
122             substr( $data_in, $head_index ) );
123              
124 112 100 100     504 if ( defined $bone->{tag} && $bone->{tag} != $dt_tag ) {
125 17         87 next;
126             }
127              
128 95         143 my $parsing_bone = $bone;
129              
130 95 100       244 if ( defined $bone->{substitution} ) {
131 9 50 33     80 if ( defined $self->{val}->{ $bone->{dt} }
132             && defined
133             DEFAULT_SUBSTITUTION->{ $self->{val}->{ $bone->{dt} }->{val} } )
134             {
135             $parsing_bone =
136             BACnet::DataTypes::Utils::_property_identifier_value_wrapper(
137             DEFAULT_SUBSTITUTION->{
138             $self->{val}->{ $bone->{dt} }->{val}
139             }
140 9         45 );
141             }
142             else {
143 0         0 $self->{error} = "SequenceValue: unknown substitution";
144 0         0 return $self;
145             }
146              
147             }
148              
149 95         318 my $new_dt =
150             BACnet::DataTypes::Utils::_parse_context_dt(
151             substr( $data_in, $head_index ),
152             $parsing_bone );
153              
154 95 50       343 if ( !defined $new_dt ) {
155 0         0 $self->{error} = "SequenceValue: unexpected parse error";
156 0         0 return $self;
157             }
158              
159 95 50       421 if ( defined $new_dt->error() ) {
160 0         0 my $error = $new_dt->error();
161 0         0 $self->{error} = "SequenceValue: propagated error from($error)";
162 0         0 return $self;
163             }
164              
165 95         142 %{ $self->{val} } = ( %{ $self->{val} }, $bone->{name} => $new_dt );
  95         318  
  95         312  
166 95         288 $head_index += length( $new_dt->data() );
167             }
168              
169 44 100       114 if ( defined $context_tag ) {
170 15 50 33     45 if (
171             BACnet::DataTypes::Utils::_is_end_of_context_sequence(
172             substr( $data_in, $head_index )
173             )
174             && $context_tag == BACnet::DataTypes::Utils::_get_head_tag(
175             substr( $data_in, $head_index )
176             )
177             )
178             {
179 15         70 $head_index += BACnet::DataTypes::Utils::_get_head_length(
180             substr( $data_in, $head_index ) );
181             }
182             else {
183 0         0 $self->{error} = "SequenceValue: context lvt tag parse error";
184 0         0 $self->{data} = $data_in;
185 0         0 return $self;
186             }
187             }
188              
189 44         129 $self->{data} = substr( $data_in, 0, $head_index );
190 44         152 return $self;
191              
192 0           return $self;
193              
194             }
195              
196             1;