package XPT::InterfaceDescriptor; use strict; use warnings; use base qw(XPT); sub demarshal { my ($r_buffer, $r_offset) = @_; my $parent_interface_index = XPT::Read16($r_buffer, $r_offset); my @method_descriptors = (); my @const_descriptors = (); my $flags = 0; eval { my $num_methods = XPT::Read16($r_buffer, $r_offset); while ($num_methods --) { my $method = XPT::MethodDescriptor::demarshal($r_buffer, $r_offset); push @method_descriptors, $method; } my $num_constants = XPT::Read16($r_buffer, $r_offset); while ($num_constants --) { my $const = XPT::ConstDescriptor::demarshal($r_buffer, $r_offset); push @const_descriptors, $const; } $flags = XPT::Read8($r_buffer, $r_offset); }; if ($@) { $XPT::demarshal_retcode = 1; if ($XPT::demarshal_not_abort) { warn $@; } else { die $@; } } return new XPT::InterfaceDescriptor( parent_interface_index => $parent_interface_index, method_descriptors => \@method_descriptors, const_descriptors => \@const_descriptors, is_scriptable => ($flags & 0x80) ? 1 : 0, is_function => ($flags & 0x40) ? 1 : 0, ); } sub marshal { my $self = shift; my $method_descriptors = q{}; foreach (@{$self->{method_descriptors}}) { $method_descriptors .= $_->marshal(); } my $const_descriptors = q{}; foreach (@{$self->{const_descriptors}}) { $const_descriptors .= $_->marshal(); } my $flags = 0; $flags |= 0x80 if ($self->{is_scriptable}); $flags |= 0x40 if ($self->{is_function}); my $offset = 1 + length($XPT::data_pool); $XPT::data_pool .= XPT::Write16($self->{parent_interface_index}); $XPT::data_pool .= XPT::Write16(scalar(@{$self->{method_descriptors}})); $XPT::data_pool .= $method_descriptors; $XPT::data_pool .= XPT::Write16(scalar(@{$self->{const_descriptors}})); $XPT::data_pool .= $const_descriptors; $XPT::data_pool .= XPT::Write8($flags); return XPT::Write32($offset); } sub stringify { my $self = shift; my ($indent) = @_; $indent = q{ } x 2 unless (defined $indent); my $new_indent = $indent . q{ } x 3; my $more_indent = $new_indent . q{ } x 3; my $str = q{}; if ($self->{parent_interface_index}) { my $name; if (defined $self->{parent_interface}) { my $itf = $self->{parent_interface}; if (ref $itf) { $name = $itf->{name_space} . '::' . $itf->{name}; } else { $name = $itf; } } else { $name = "UNKNOWN_INTERFACE"; } $str .= $indent . "Parent: " . $name . "\n" } $str .= $indent . "Flags:\n"; $str .= $new_indent . "Scriptable: " . ($self->{is_scriptable} ? 'TRUE' : 'FALSE') . "\n"; $str .= $new_indent . "Function: " . ($self->{is_function} ? 'TRUE' : 'FALSE') . "\n"; if ($XPT::stringify_verbose and exists $self->{parent_interface_index}) { $str .= $indent . "Index of parent interface (in data pool): "; $str .= $self->{parent_interface_index} . "\n"; } if (scalar @{$self->{method_descriptors}}) { if ($XPT::stringify_verbose) { $str .= $indent . "# of Method Descriptors: "; $str .= scalar(@{$self->{method_descriptors}}) . "\n"; } else { $str .= $indent . "Methods:\n"; } my $nb = 0; foreach (@{$self->{method_descriptors}}) { if ($XPT::stringify_verbose) { $str .= $new_indent . "Method #" . $nb ++ . ":\n"; $str .= $_->stringify($more_indent); } else { $str .= $_->stringify($new_indent); } } } else { $str .= $indent . "Methods:\n"; $str .= $new_indent . "No Methods\n"; } if (scalar @{$self->{const_descriptors}}) { if ($XPT::stringify_verbose) { $str .= $indent . "# of Constant Descriptors: "; $str .= scalar(@{$self->{const_descriptors}}) . "\n"; } else { $str .= $indent . "Constants:\n"; } my $nb = 0; foreach (@{$self->{const_descriptors}}) { if ($XPT::stringify_verbose) { $str .= $new_indent . "Constant #" . $nb ++ . ":\n"; $str .= $_->stringify($more_indent); } else { $str .= $_->stringify($new_indent); } } } else { $str .= $indent . "Constants:\n"; $str .= $new_indent . "No Constants\n"; } return $str; } 1;