File Coverage

blib/lib/Google/ProtocolBuffers/CodeGen.pm
Criterion Covered Total %
statement 51 59 86.4
branch 17 20 85.0
condition 5 9 55.5
subroutine 6 6 100.0
pod 0 2 0.0
total 79 96 82.2


line stmt bran cond sub pod time code
1             package Google::ProtocolBuffers::CodeGen;
2 1     1   7 use strict;
  1         1  
  1         44  
3 1     1   6 use warnings;
  1         2  
  1         71  
4            
5 1     1   7 use Google::ProtocolBuffers::Constants qw/:types :labels :complex_types/;
  1         1  
  1         1446  
6            
7             my %primitive_types = reverse (
8             TYPE_DOUBLE => TYPE_DOUBLE,
9             TYPE_FLOAT => TYPE_FLOAT,
10             TYPE_INT64 => TYPE_INT64,
11             TYPE_UINT64 => TYPE_UINT64,
12             TYPE_INT32 => TYPE_INT32,
13             TYPE_FIXED64=> TYPE_FIXED64,
14             TYPE_FIXED32=> TYPE_FIXED32,
15             TYPE_BOOL => TYPE_BOOL,
16             TYPE_STRING => TYPE_STRING,
17             TYPE_GROUP => TYPE_GROUP, ##
18             TYPE_MESSAGE=> TYPE_MESSAGE, ## should never appear, because 'message' is a 'complex type'
19             TYPE_BYTES => TYPE_BYTES,
20             TYPE_UINT32 => TYPE_UINT32,
21             TYPE_ENUM => TYPE_ENUM, ##
22             TYPE_SFIXED32=>TYPE_SFIXED32,
23             TYPE_SFIXED64=>TYPE_SFIXED64,
24             TYPE_SINT32 => TYPE_SINT32,
25             TYPE_SINT64 => TYPE_SINT64,
26             );
27            
28             my %labels = reverse (
29             LABEL_OPTIONAL => LABEL_OPTIONAL,
30             LABEL_REQUIRED => LABEL_REQUIRED,
31             LABEL_REPEATED => LABEL_REPEATED,
32             );
33            
34             sub _get_perl_literal {
35 79     79   56 my $v = shift;
36 79         47 my $opts = shift;
37            
38 79 100       168 if ($v =~ /^-?\d+$/) {
    100          
39             ## integer literal
40 55 100 100     134 if ($v>0x7fff_ffff || $v<-0x8000_0000) {
41 3         6 return "Math::BigInt->new('$v')";
42             } else {
43 52         57 return "$v";
44             }
45             } elsif ($v =~ /[-+]?\d*\.\d+([Ee][\+-]?\d+)?|[-+]?\d+[Ee][\+-]?\d+/i) {
46             ## floating point literal
47 4         7 return "$v";
48             } else {
49             ## string literal
50 20         57 $v =~ s/([\x00-\x1f'"\\$@%\x80-\xff])/ '\\x{' . sprintf("%02x", ord($1)) . '}' /ge;
  16         31  
51 20         31 return qq["$v"];
52             }
53             }
54            
55             sub generate_code_of_enum {
56 5     5 0 5 my $self = shift;
57 5         4 my $opts = shift;
58            
59 5   33     14 my $class_name = ref($self) || $self;
60 5         4 my $fields_text;
61 5         5 foreach my $f (@{ $self->_pb_fields_list }) {
  5         13  
62 21         32 my ($name, $value) = @$f;
63 21         21 $value = _get_perl_literal($value, $opts);
64 21         34 $fields_text .= " ['$name', $value],\n";
65             }
66            
67 5         18 return <<"CODE";
68             unless ($class_name->can('_pb_fields_list')) {
69             Google::ProtocolBuffers->create_enum(
70             '$class_name',
71             [
72             $fields_text
73             ]
74             );
75             }
76            
77             CODE
78             }
79            
80            
81             sub generate_code_of_message_or_group {
82 34     34 0 30 my $self = shift;
83 34         29 my $opts = shift;
84            
85 34 50       108 my $create_what =
    100          
86             ($self->_pb_complex_type_kind==MESSAGE) ? 'create_message' :
87             ($self->_pb_complex_type_kind==GROUP) ? 'create_group' : die;
88            
89 34   33     92 my $class_name = ref($self) || $self;
90            
91 34         21 my $fields_text = ''; # may be empty, as empty messages are allowed
92 34         30 foreach my $f (@{ $self->_pb_fields_list }) {
  34         85  
93 226         310 my ($label, $type, $name, $field_number, $default_value) = @$f;
94            
95 226 50       305 die unless $labels{$label};
96 226         196 $label = "Google::ProtocolBuffers::Constants::$labels{$label}()";
97            
98 226 100       249 if ($primitive_types{$type}) {
99 176         169 $type = "Google::ProtocolBuffers::Constants::$primitive_types{$type}()";
100             } else {
101 50         45 $type = "'$type'";
102             }
103            
104 226 100       226 $default_value = (defined $default_value) ?
105             _get_perl_literal($default_value, $opts) : 'undef';
106 226         395 $fields_text .= <<"FIELD";
107             [
108             $label,
109             $type,
110             '$name', $field_number, $default_value
111             ],
112             FIELD
113             }
114            
115 34         28 my $oneofs_text = " undef,\n";
116 34 50       246 if ($self->can('_pb_oneofs')) {
117 0         0 $oneofs_text = " {\n";
118 0         0 while (my ($name, $fields) = each %{$self->_pb_oneofs}) {
  0         0  
119 0         0 $oneofs_text .= " '$name' => [\n";
120 0         0 foreach my $f (@$fields) {
121 0         0 $oneofs_text .= " '$f',\n";
122             }
123 0         0 $oneofs_text .= " ],\n";
124             }
125 0         0 $oneofs_text .= " },\n";
126             }
127              
128 34         33 my $options = '';
129 34         34 foreach my $opt_name (qw/create_accessors follow_best_practice/) {
130 68 100       107 if ($opts->{$opt_name}) {
131 34         45 $options .= "'$opt_name' => 1, "
132             }
133             }
134            
135 34         367 return <<"CODE";
136             unless ($class_name->can('_pb_fields_list')) {
137             Google::ProtocolBuffers->$create_what(
138             '$class_name',
139             [
140             $fields_text
141             ],
142             $oneofs_text
143             { $options }
144             );
145             }
146            
147             CODE
148            
149             }
150            
151             1;