File Coverage

blib/lib/PJVM/Class.pm
Criterion Covered Total %
statement 75 75 100.0
branch 7 12 58.3
condition 2 3 66.6
subroutine 11 11 100.0
pod 0 5 0.0
total 95 106 89.6


line stmt bran cond sub pod time code
1             package PJVM::Class;
2              
3 3     3   17 use strict;
  3         6  
  3         104  
4 3     3   17 use warnings;
  3         14  
  3         115  
5              
6 3     3   1793 use PJVM::Class::ConstantPool;
  3         8  
  3         99  
7 3     3   2875 use PJVM::Class::Field;
  3         11  
  3         30  
8 3     3   1990 use PJVM::Class::Method;
  3         11  
  3         85  
9              
10 3         14 use Object::Tiny qw(
11             constant_pool
12             access_flags
13             this_class
14             super_class
15             interfaces_classes
16             fields
17             methods
18             attributes
19 3     3   164 );
  3         4  
20              
21             sub new_from_io {
22 3     3 0 7 my ($pkg, $io) = @_;
23            
24 3         7 my $buff;
25            
26 3         34 my $self = $pkg->new();
27            
28             # Check that's it is actually a class file
29 3         113 read $io, $buff, 4;
30 3 50       43 die "Not a classfile" unless sprintf("%x", unpack("N", $buff)) eq "cafebabe";
31            
32             # TODO: Blah blah blah.. version compliance crap, let's skip this for now and
33             # maybe sometime in the future do something with it.
34 3         8 read $io, $buff, 4;
35            
36             # Constant pool count.. here lies our constants, ie class names etc.
37 3         34 my $cp = PJVM::Class::ConstantPool->new_from_io($io);
38 3         21 $self->{constant_pool} = $cp;
39              
40             # Access flags (you know, public etc...)
41 3         17 read $io, $buff, 2;
42 3         9 my $access_flags = unpack("n", $buff);
43 3         12 $self->{access_flags} = $access_flags,
44            
45             # Name of class and parent
46             read $io, $buff, 4;
47 3         9 my ($this_class, $super_class) = unpack("nn", $buff);
48 3         14 $self->{this_class} = $this_class,
49             $self->{super_class} = $super_class,
50            
51             # Read interfaces
52             read $io, $buff, 2;
53 3         19 my $interface_count = unpack("n", $buff);
54 3         6 my @interfaces;
55 3 50       11 if ($interface_count) {
56 3         9 read $io, $buff, 2 * $interface_count;
57 3         18 @interfaces = unpack("n*", $buff);
58             }
59 3         29 $self->{interfaces_classes} = \@interfaces,
60            
61             # Read fields
62             read $io, $buff, 2;
63 3         8 my $fields_count = unpack("n", $buff);
64 3         5 my @fields;
65 3 50       22 if ($fields_count) {
66 3         19 while ($fields_count--) {
67 9         46 push @fields, PJVM::Class::Field->new_from_io($io, $cp, $self);
68             }
69             }
70 3         12 $self->{fields} = \@fields,
71            
72             # Read methods
73             read $io, $buff, 2;
74 3         8 my $methods_count = unpack("n", $buff);
75 3         5 my @methods;
76 3 50       19 if ($methods_count) {
77 3         11 while ($methods_count--) {
78 9         64 push @methods, PJVM::Class::Method->new_from_io($io, $cp, $self);
79             }
80             }
81 3         100 $self->{methods} = \@methods,
82            
83             # Attributes
84             read $io, $buff, 2;
85 3         10 my $attributes_count = unpack("n", $buff);
86            
87             # Read attributes
88 3         5 my @attributes;
89 3 50       13 if ($attributes_count) {
90 3         17 while ($attributes_count--) {
91 3         14 push @attributes, PJVM::Class::Attribute->new_from_io($io, $cp);
92             }
93             }
94 3         21 $self->{attributes} = \@attributes,
95            
96             return $self;
97             }
98              
99             # TODO: Optimize since this will probablly be called mucho tiempo
100             sub method {
101 1     1 0 7 my ($self, $name, $signature) = @_;
102              
103 1         2 for my $method (@{$self->methods}) {
  1         28  
104 3 100 66     33 if ($method->name eq $name && $method->signature eq $signature) {
105 1         12 return $method;
106             }
107             }
108             }
109              
110             sub name {
111 1     1 0 4 my $self = shift;
112 1         21 my $class = $self->constant_pool->get($self->this_class);
113 1         18 my $name = $self->constant_pool->get($class->name_index);
114            
115 1         17 return $name->value;
116             }
117              
118             sub super {
119 1     1 0 765 my $self = shift;
120 1         22 my $class = $self->constant_pool->get($self->super_class);
121 1         19 my $name = $self->constant_pool->get($class->name_index);
122            
123 1         18 return $name->value;
124             }
125              
126             sub interfaces {
127 1     1 0 319 my $self = shift;
128 1         23 my @names = map {
129 1         21 my $class = $self->constant_pool->get($_);
130 1         18 my $name = $self->constant_pool->get($class->name_index);
131 1         25 $name->value;
132 1         3 } @{$self->interfaces_classes};
133            
134 1         16 return @names;
135             }
136              
137             1;
138             __END__