| Filename | /usr/share/perl5/Convert/ASN1.pm |
| Statements | Executed 481 statements in 4.81ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 11.8ms | 13.8ms | Convert::ASN1::BEGIN@415 |
| 74 | 1 | 1 | 638µs | 638µs | Convert::ASN1::asn_tag |
| 1 | 1 | 1 | 267µs | 271µs | Convert::ASN1::BEGIN@16 |
| 105 | 3 | 1 | 216µs | 216µs | Convert::ASN1::asn_encode_tag |
| 1 | 1 | 1 | 89µs | 89µs | Convert::ASN1::_internal_syms |
| 1 | 1 | 1 | 67µs | 67µs | Convert::ASN1::BEGIN@9 |
| 1 | 1 | 1 | 34µs | 103ms | Convert::ASN1::prepare |
| 1 | 1 | 1 | 28µs | 137µs | Convert::ASN1::BEGIN@14 |
| 1 | 1 | 1 | 26µs | 31µs | Convert::ASN1::configure |
| 2 | 1 | 1 | 24µs | 24µs | Convert::ASN1::find |
| 1 | 1 | 1 | 23µs | 211µs | Convert::ASN1::BEGIN@11 |
| 1 | 1 | 1 | 23µs | 57µs | Convert::ASN1::BEGIN@12 |
| 1 | 1 | 1 | 21µs | 32µs | Convert::ASN1::BEGIN@10 |
| 1 | 1 | 1 | 21µs | 52µs | Convert::ASN1::new |
| 1 | 1 | 1 | 16µs | 38µs | Convert::ASN1::BEGIN@67 |
| 1 | 1 | 1 | 15µs | 49µs | Convert::ASN1::BEGIN@59 |
| 1 | 1 | 1 | 5µs | 5µs | Convert::ASN1::CORE:match (opcode) |
| 1 | 1 | 1 | 3µs | 3µs | Convert::ASN1::_pack_struct |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::AUTOLOAD |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::DESTROY |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::__ANON__[:60] |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::_unpack_struct |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::asn_decode_length |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::asn_decode_tag |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::asn_decode_tag2 |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::asn_encode_length |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::decode |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::encode |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::error |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::i2osp |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::num_length |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::os2ip |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::prepare_file |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::registeroid |
| 0 | 0 | 0 | 0s | 0s | Convert::ASN1::registertype |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | # Copyright (c) 2000-2002 Graham Barr <gbarr@pobox.com>. All rights reserved. | ||||
| 2 | # This program is free software; you can redistribute it and/or | ||||
| 3 | # modify it under the same terms as Perl itself. | ||||
| 4 | |||||
| 5 | package Convert::ASN1; | ||||
| 6 | |||||
| 7 | # $Id: ASN1.pm,v 1.29 2003/10/08 14:29:17 gbarr Exp $ | ||||
| 8 | |||||
| 9 | 3 | 88µs | 1 | 67µs | # spent 67µs within Convert::ASN1::BEGIN@9 which was called:
# once (67µs+0s) by Net::LDAP::BEGIN@12 at line 9 # spent 67µs making 1 call to Convert::ASN1::BEGIN@9 |
| 10 | 3 | 111µs | 2 | 42µs | # spent 32µs (21+10) within Convert::ASN1::BEGIN@10 which was called:
# once (21µs+10µs) by Net::LDAP::BEGIN@12 at line 10 # spent 32µs making 1 call to Convert::ASN1::BEGIN@10
# spent 10µs making 1 call to strict::import |
| 11 | 3 | 57µs | 2 | 399µs | # spent 211µs (23+188) within Convert::ASN1::BEGIN@11 which was called:
# once (23µs+188µs) by Net::LDAP::BEGIN@12 at line 11 # spent 211µs making 1 call to Convert::ASN1::BEGIN@11
# spent 188µs making 1 call to vars::import |
| 12 | 3 | 74µs | 2 | 91µs | # spent 57µs (23+34) within Convert::ASN1::BEGIN@12 which was called:
# once (23µs+34µs) by Net::LDAP::BEGIN@12 at line 12 # spent 57µs making 1 call to Convert::ASN1::BEGIN@12
# spent 34µs making 1 call to Exporter::import |
| 13 | |||||
| 14 | 3 | 336µs | 2 | 247µs | # spent 137µs (28+109) within Convert::ASN1::BEGIN@14 which was called:
# once (28µs+109µs) by Net::LDAP::BEGIN@12 at line 14 # spent 137µs making 1 call to Convert::ASN1::BEGIN@14
# spent 109µs making 1 call to constant::import |
| 15 | |||||
| 16 | # spent 271µs (267+4) within Convert::ASN1::BEGIN@16 which was called:
# once (267µs+4µs) by Net::LDAP::BEGIN@12 at line 63 | ||||
| 17 | 1 | 5µs | local $SIG{__DIE__}; | ||
| 18 | 2 | 9µs | 1 | 4µs | eval { require bytes and 'bytes'->import }; # spent 4µs making 1 call to bytes::import |
| 19 | |||||
| 20 | 1 | 500ns | if (CHECK_UTF8) { | ||
| 21 | 1 | 900ns | require Encode; | ||
| 22 | 1 | 1µs | require utf8; | ||
| 23 | } | ||||
| 24 | |||||
| 25 | 1 | 9µs | @ISA = qw(Exporter); | ||
| 26 | 1 | 600ns | $VERSION = "0.22"; | ||
| 27 | |||||
| 28 | 1 | 14µs | %EXPORT_TAGS = ( | ||
| 29 | io => [qw(asn_recv asn_send asn_read asn_write asn_get asn_ready)], | ||||
| 30 | |||||
| 31 | debug => [qw(asn_dump asn_hexdump)], | ||||
| 32 | |||||
| 33 | const => [qw(ASN_BOOLEAN ASN_INTEGER ASN_BIT_STR ASN_OCTET_STR | ||||
| 34 | ASN_NULL ASN_OBJECT_ID ASN_REAL ASN_ENUMERATED | ||||
| 35 | ASN_SEQUENCE ASN_SET ASN_PRINT_STR ASN_IA5_STR | ||||
| 36 | ASN_UTC_TIME ASN_GENERAL_TIME ASN_RELATIVE_OID | ||||
| 37 | ASN_UNIVERSAL ASN_APPLICATION ASN_CONTEXT ASN_PRIVATE | ||||
| 38 | ASN_PRIMITIVE ASN_CONSTRUCTOR ASN_LONG_LEN ASN_EXTENSION_ID ASN_BIT)], | ||||
| 39 | |||||
| 40 | tag => [qw(asn_tag asn_decode_tag2 asn_decode_tag asn_encode_tag asn_decode_length asn_encode_length)] | ||||
| 41 | ); | ||||
| 42 | |||||
| 43 | 1 | 22µs | @EXPORT_OK = map { @$_ } values %EXPORT_TAGS; | ||
| 44 | 1 | 2µs | $EXPORT_TAGS{all} = \@EXPORT_OK; | ||
| 45 | |||||
| 46 | 1 | 1µs | @opParts = qw( | ||
| 47 | cTAG cTYPE cVAR cLOOP cOPT cCHILD cDEFINE | ||||
| 48 | ); | ||||
| 49 | |||||
| 50 | 1 | 2µs | @opName = qw( | ||
| 51 | opUNKNOWN opBOOLEAN opINTEGER opBITSTR opSTRING opNULL opOBJID opREAL | ||||
| 52 | opSEQUENCE opSET opUTIME opGTIME opUTF8 opANY opCHOICE opROID opBCD | ||||
| 53 | ); | ||||
| 54 | |||||
| 55 | 1 | 10µs | foreach my $l (\@opParts, \@opName) { | ||
| 56 | 2 | 700ns | my $i = 0; | ||
| 57 | 2 | 3µs | foreach my $name (@$l) { | ||
| 58 | 24 | 8µs | my $j = $i++; | ||
| 59 | 3 | 93µs | 2 | 82µs | # spent 49µs (15+33) within Convert::ASN1::BEGIN@59 which was called:
# once (15µs+33µs) by Net::LDAP::BEGIN@12 at line 59 # spent 49µs making 1 call to Convert::ASN1::BEGIN@59
# spent 33µs making 1 call to strict::unimport |
| 60 | *{__PACKAGE__ . '::' . $name} = sub () { $j } | ||||
| 61 | 24 | 171µs | } | ||
| 62 | } | ||||
| 63 | 1 | 85µs | 1 | 271µs | } # spent 271µs making 1 call to Convert::ASN1::BEGIN@16 |
| 64 | |||||
| 65 | # spent 89µs within Convert::ASN1::_internal_syms which was called:
# once (89µs+0s) by Convert::ASN1::parser::BEGIN@16 at line 16 of Convert/ASN1/parser.pm | ||||
| 66 | 1 | 1µs | my $pkg = caller; | ||
| 67 | 3 | 1.93ms | 2 | 61µs | # spent 38µs (16+22) within Convert::ASN1::BEGIN@67 which was called:
# once (16µs+22µs) by Net::LDAP::BEGIN@12 at line 67 # spent 38µs making 1 call to Convert::ASN1::BEGIN@67
# spent 22µs making 1 call to strict::unimport |
| 68 | 1 | 12µs | for my $sub (@opParts,@opName,'dump_op') { | ||
| 69 | 25 | 84µs | *{$pkg . '::' . $sub} = \&{__PACKAGE__ . '::' . $sub}; | ||
| 70 | } | ||||
| 71 | } | ||||
| 72 | |||||
| 73 | sub ASN_BOOLEAN () { 0x01 } | ||||
| 74 | sub ASN_INTEGER () { 0x02 } | ||||
| 75 | sub ASN_BIT_STR () { 0x03 } | ||||
| 76 | sub ASN_OCTET_STR () { 0x04 } | ||||
| 77 | sub ASN_NULL () { 0x05 } | ||||
| 78 | sub ASN_OBJECT_ID () { 0x06 } | ||||
| 79 | sub ASN_REAL () { 0x09 } | ||||
| 80 | sub ASN_ENUMERATED () { 0x0A } | ||||
| 81 | sub ASN_RELATIVE_OID () { 0x0D } | ||||
| 82 | sub ASN_SEQUENCE () { 0x10 } | ||||
| 83 | sub ASN_SET () { 0x11 } | ||||
| 84 | sub ASN_PRINT_STR () { 0x13 } | ||||
| 85 | sub ASN_IA5_STR () { 0x16 } | ||||
| 86 | sub ASN_UTC_TIME () { 0x17 } | ||||
| 87 | sub ASN_GENERAL_TIME () { 0x18 } | ||||
| 88 | |||||
| 89 | sub ASN_UNIVERSAL () { 0x00 } | ||||
| 90 | sub ASN_APPLICATION () { 0x40 } | ||||
| 91 | sub ASN_CONTEXT () { 0x80 } | ||||
| 92 | sub ASN_PRIVATE () { 0xC0 } | ||||
| 93 | |||||
| 94 | sub ASN_PRIMITIVE () { 0x00 } | ||||
| 95 | sub ASN_CONSTRUCTOR () { 0x20 } | ||||
| 96 | |||||
| 97 | sub ASN_LONG_LEN () { 0x80 } | ||||
| 98 | sub ASN_EXTENSION_ID () { 0x1F } | ||||
| 99 | sub ASN_BIT () { 0x80 } | ||||
| 100 | |||||
| 101 | |||||
| 102 | # spent 52µs (21+31) within Convert::ASN1::new which was called:
# once (21µs+31µs) by Net::LDAP::Message::BEGIN@8 at line 8 of Net/LDAP/ASN.pm | ||||
| 103 | 1 | 2µs | my $pkg = shift; | ||
| 104 | 1 | 10µs | my $self = bless {}, $pkg; | ||
| 105 | |||||
| 106 | 1 | 4µs | 1 | 31µs | $self->configure(@_); # spent 31µs making 1 call to Convert::ASN1::configure |
| 107 | 1 | 4µs | $self; | ||
| 108 | } | ||||
| 109 | |||||
| 110 | |||||
| 111 | # spent 31µs (26+5) within Convert::ASN1::configure which was called:
# once (26µs+5µs) by Convert::ASN1::new at line 106 | ||||
| 112 | 1 | 600ns | my $self = shift; | ||
| 113 | 1 | 2µs | my %opt = @_; | ||
| 114 | |||||
| 115 | 1 | 5µs | $self->{options}{encoding} = uc($opt{encoding} || 'BER'); | ||
| 116 | |||||
| 117 | 1 | 18µs | 1 | 5µs | unless ($self->{options}{encoding} =~ /^[BD]ER$/) { # spent 5µs making 1 call to Convert::ASN1::CORE:match |
| 118 | require Carp; | ||||
| 119 | Carp::croak("Unsupported encoding format '$opt{encoding}'"); | ||||
| 120 | } | ||||
| 121 | |||||
| 122 | 1 | 6µs | for my $type (qw(encode decode)) { | ||
| 123 | 2 | 2µs | if (exists $opt{$type}) { | ||
| 124 | while(my($what,$value) = each %{$opt{$type}}) { | ||||
| 125 | $self->{options}{"${type}_${what}"} = $value; | ||||
| 126 | } | ||||
| 127 | } | ||||
| 128 | } | ||||
| 129 | } | ||||
| 130 | |||||
| - - | |||||
| 133 | # spent 24µs within Convert::ASN1::find which was called 2 times, avg 12µs/call:
# 2 times (24µs+0s) by Net::LDAP::ASN::import at line 15 of Net/LDAP/ASN.pm, avg 12µs/call | ||||
| 134 | 2 | 1µs | my $self = shift; | ||
| 135 | 2 | 1µs | my $what = shift; | ||
| 136 | 2 | 3µs | return unless exists $self->{tree}{$what}; | ||
| 137 | 2 | 8µs | my %new = %$self; | ||
| 138 | 2 | 3µs | $new{script} = $new{tree}->{$what}; | ||
| 139 | 2 | 13µs | bless \%new, ref($self); | ||
| 140 | } | ||||
| 141 | |||||
| 142 | |||||
| 143 | # spent 103ms (34µs+103) within Convert::ASN1::prepare which was called:
# once (34µs+103ms) by Net::LDAP::Message::BEGIN@8 at line 22 of Net/LDAP/ASN.pm | ||||
| 144 | 1 | 800ns | my $self = shift; | ||
| 145 | 1 | 4µs | my $asn = shift; | ||
| 146 | |||||
| 147 | 1 | 1µs | $self = $self->new unless ref($self); | ||
| 148 | 1 | 400ns | my $tree; | ||
| 149 | 1 | 2µs | if( ref($asn) eq 'GLOB' ){ | ||
| 150 | local $/ = undef; | ||||
| 151 | my $txt = <$asn>; | ||||
| 152 | $tree = Convert::ASN1::parser::parse($txt); | ||||
| 153 | } else { | ||||
| 154 | 1 | 4µs | 1 | 103ms | $tree = Convert::ASN1::parser::parse($asn); # spent 103ms making 1 call to Convert::ASN1::parser::parse |
| 155 | } | ||||
| 156 | |||||
| 157 | 1 | 900ns | unless ($tree) { | ||
| 158 | $self->{error} = $@; | ||||
| 159 | return; | ||||
| 160 | ### If $self has been set to a new object, not returning | ||||
| 161 | ### this object here will destroy the object, so the caller | ||||
| 162 | ### won't be able to get at the error. | ||||
| 163 | } | ||||
| 164 | |||||
| 165 | 1 | 6µs | 1 | 3µs | $self->{tree} = _pack_struct($tree); # spent 3µs making 1 call to Convert::ASN1::_pack_struct |
| 166 | 1 | 7µs | $self->{script} = (values %$tree)[0]; | ||
| 167 | 1 | 6µs | $self; | ||
| 168 | } | ||||
| 169 | |||||
| 170 | sub prepare_file { | ||||
| 171 | my $self = shift; | ||||
| 172 | my $asnp = shift; | ||||
| 173 | |||||
| 174 | local *ASN; | ||||
| 175 | open( ASN, $asnp ) | ||||
| 176 | or do{ $self->{error} = $@; return; }; | ||||
| 177 | my $ret = $self->prepare( \*ASN ); | ||||
| 178 | close( ASN ); | ||||
| 179 | $ret; | ||||
| 180 | } | ||||
| 181 | |||||
| 182 | sub registeroid { | ||||
| 183 | my $self = shift; | ||||
| 184 | my $oid = shift; | ||||
| 185 | my $handler = shift; | ||||
| 186 | |||||
| 187 | $self->{options}{oidtable}{$oid}=$handler; | ||||
| 188 | $self->{oidtable}{$oid}=$handler; | ||||
| 189 | } | ||||
| 190 | |||||
| 191 | sub registertype { | ||||
| 192 | my $self = shift; | ||||
| 193 | my $def = shift; | ||||
| 194 | my $type = shift; | ||||
| 195 | my $handler = shift; | ||||
| 196 | |||||
| 197 | $self->{options}{handlers}{$def}{$type}=$handler; | ||||
| 198 | } | ||||
| 199 | |||||
| 200 | # In XS the will convert the tree between perl and C structs | ||||
| 201 | |||||
| 202 | 1 | 5µs | # spent 3µs within Convert::ASN1::_pack_struct which was called:
# once (3µs+0s) by Convert::ASN1::prepare at line 165 | ||
| 203 | sub _unpack_struct { $_[0] } | ||||
| 204 | |||||
| 205 | ## | ||||
| 206 | ## Encoding | ||||
| 207 | ## | ||||
| 208 | |||||
| 209 | sub encode { | ||||
| 210 | my $self = shift; | ||||
| 211 | my $stash = @_ == 1 ? shift : { @_ }; | ||||
| 212 | my $buf = ''; | ||||
| 213 | local $SIG{__DIE__}; | ||||
| 214 | eval { _encode($self->{options}, $self->{script}, $stash, [], $buf) } | ||||
| 215 | or do { $self->{error} = $@; undef } | ||||
| 216 | } | ||||
| 217 | |||||
| - - | |||||
| 220 | # Encode tag value for encoding. | ||||
| 221 | # We assume that the tag has been correctly generated with asn_tag() | ||||
| 222 | |||||
| 223 | # spent 216µs within Convert::ASN1::asn_encode_tag which was called 105 times, avg 2µs/call:
# 45 times (106µs+0s) by Convert::ASN1::parser::compile_one at line 679 of Convert/ASN1/parser.pm, avg 2µs/call
# 31 times (42µs+0s) by Convert::ASN1::BEGIN@415 at line 21 of Convert/ASN1/parser.pm, avg 1µs/call
# 29 times (69µs+0s) by Convert::ASN1::parser::compile_one at line 664 of Convert/ASN1/parser.pm, avg 2µs/call | ||||
| 224 | 105 | 314µs | $_[0] >> 8 | ||
| 225 | ? $_[0] & 0x8000 | ||||
| 226 | ? $_[0] & 0x800000 | ||||
| 227 | ? pack("V",$_[0]) | ||||
| 228 | : substr(pack("V",$_[0]),0,3) | ||||
| 229 | : pack("v", $_[0]) | ||||
| 230 | : chr($_[0]); | ||||
| 231 | } | ||||
| 232 | |||||
| 233 | |||||
| 234 | # Encode a length. If < 0x80 then encode as a byte. Otherwise encode | ||||
| 235 | # 0x80 | num_bytes followed by the bytes for the number. top end | ||||
| 236 | # bytes of all zeros are not encoded | ||||
| 237 | |||||
| 238 | sub asn_encode_length { | ||||
| 239 | |||||
| 240 | if($_[0] >> 7) { | ||||
| 241 | my $lenlen = &num_length; | ||||
| 242 | |||||
| 243 | return pack("Ca*", $lenlen | 0x80, substr(pack("N",$_[0]), -$lenlen)); | ||||
| 244 | } | ||||
| 245 | |||||
| 246 | return pack("C", $_[0]); | ||||
| 247 | } | ||||
| 248 | |||||
| 249 | |||||
| 250 | ## | ||||
| 251 | ## Decoding | ||||
| 252 | ## | ||||
| 253 | |||||
| 254 | sub decode { | ||||
| 255 | my $self = shift; | ||||
| 256 | |||||
| 257 | local $SIG{__DIE__}; | ||||
| 258 | my $ret = eval { | ||||
| 259 | my (%stash, $result); | ||||
| 260 | my $script = $self->{script}; | ||||
| 261 | my $stash = (1 == @$script && !$self->{script}[0][cVAR]) ? \$result : ($result=\%stash); | ||||
| 262 | |||||
| 263 | _decode( | ||||
| 264 | $self->{options}, | ||||
| 265 | $script, | ||||
| 266 | $stash, | ||||
| 267 | 0, | ||||
| 268 | length $_[0], | ||||
| 269 | undef, | ||||
| 270 | {}, | ||||
| 271 | $_[0]); | ||||
| 272 | |||||
| 273 | $result; | ||||
| 274 | }; | ||||
| 275 | if ($@) { | ||||
| 276 | $self->{'error'} = $@; | ||||
| 277 | return undef; | ||||
| 278 | } | ||||
| 279 | $ret; | ||||
| 280 | } | ||||
| 281 | |||||
| 282 | |||||
| 283 | sub asn_decode_length { | ||||
| 284 | return unless length $_[0]; | ||||
| 285 | |||||
| 286 | my $len = ord substr($_[0],0,1); | ||||
| 287 | |||||
| 288 | if($len & 0x80) { | ||||
| 289 | $len &= 0x7f or return (1,-1); | ||||
| 290 | |||||
| 291 | return if $len >= length $_[0]; | ||||
| 292 | |||||
| 293 | return (1+$len, unpack("N", "\0" x (4 - $len) . substr($_[0],1,$len))); | ||||
| 294 | } | ||||
| 295 | return (1, $len); | ||||
| 296 | } | ||||
| 297 | |||||
| 298 | |||||
| 299 | sub asn_decode_tag { | ||||
| 300 | return unless length $_[0]; | ||||
| 301 | |||||
| 302 | my $tag = ord $_[0]; | ||||
| 303 | my $n = 1; | ||||
| 304 | |||||
| 305 | if(($tag & 0x1f) == 0x1f) { | ||||
| 306 | my $b; | ||||
| 307 | do { | ||||
| 308 | return if $n >= length $_[0]; | ||||
| 309 | $b = ord substr($_[0],$n,1); | ||||
| 310 | $tag |= $b << (8 * $n++); | ||||
| 311 | } while($b & 0x80); | ||||
| 312 | } | ||||
| 313 | ($n, $tag); | ||||
| 314 | } | ||||
| 315 | |||||
| 316 | |||||
| 317 | sub asn_decode_tag2 { | ||||
| 318 | return unless length $_[0]; | ||||
| 319 | |||||
| 320 | my $tag = ord $_[0]; | ||||
| 321 | my $num = $tag & 0x1f; | ||||
| 322 | my $len = 1; | ||||
| 323 | |||||
| 324 | if($num == 0x1f) { | ||||
| 325 | $num = 0; | ||||
| 326 | my $b; | ||||
| 327 | do { | ||||
| 328 | return if $len >= length $_[0]; | ||||
| 329 | $b = ord substr($_[0],$len++,1); | ||||
| 330 | $num = ($num << 7) + ($b & 0x7f); | ||||
| 331 | } while($b & 0x80); | ||||
| 332 | } | ||||
| 333 | ($len, $tag, $num); | ||||
| 334 | } | ||||
| 335 | |||||
| 336 | |||||
| 337 | ## | ||||
| 338 | ## Utilities | ||||
| 339 | ## | ||||
| 340 | |||||
| 341 | # How many bytes are needed to encode a number | ||||
| 342 | |||||
| 343 | sub num_length { | ||||
| 344 | $_[0] >> 8 | ||||
| 345 | ? $_[0] >> 16 | ||||
| 346 | ? $_[0] >> 24 | ||||
| 347 | ? 4 | ||||
| 348 | : 3 | ||||
| 349 | : 2 | ||||
| 350 | : 1 | ||||
| 351 | } | ||||
| 352 | |||||
| 353 | # Convert from a bigint to an octet string | ||||
| 354 | |||||
| 355 | sub i2osp { | ||||
| 356 | my($num, $biclass) = @_; | ||||
| 357 | eval "use $biclass"; | ||||
| 358 | $num = $biclass->new($num); | ||||
| 359 | my $neg = $num < 0 | ||||
| 360 | and $num = abs($num+1); | ||||
| 361 | my $base = $biclass->new(256); | ||||
| 362 | my $result = ''; | ||||
| 363 | while($num != 0) { | ||||
| 364 | my $r = $num % $base; | ||||
| 365 | $num = ($num-$r) / $base; | ||||
| 366 | $result .= chr($r); | ||||
| 367 | } | ||||
| 368 | $result ^= chr(255) x length($result) if $neg; | ||||
| 369 | return scalar reverse $result; | ||||
| 370 | } | ||||
| 371 | |||||
| 372 | # Convert from an octet string to a bigint | ||||
| 373 | |||||
| 374 | sub os2ip { | ||||
| 375 | my($os, $biclass) = @_; | ||||
| 376 | eval "require $biclass"; | ||||
| 377 | my $base = $biclass->new(256); | ||||
| 378 | my $result = $biclass->new(0); | ||||
| 379 | my $neg = ord($os) >= 0x80 | ||||
| 380 | and $os ^= chr(255) x length($os); | ||||
| 381 | for (unpack("C*",$os)) { | ||||
| 382 | $result = ($result * $base) + $_; | ||||
| 383 | } | ||||
| 384 | return $neg ? ($result + 1) * -1 : $result; | ||||
| 385 | } | ||||
| 386 | |||||
| 387 | # Given a class and a tag, calculate an integer which when encoded | ||||
| 388 | # will become the tag. This means that the class bits are always | ||||
| 389 | # in the bottom byte, so are the tag bits if tag < 30. Otherwise | ||||
| 390 | # the tag is in the upper 3 bytes. The upper bytes are encoded | ||||
| 391 | # with bit8 representing that there is another byte. This | ||||
| 392 | # means the max tag we can do is 0x1fffff | ||||
| 393 | |||||
| 394 | # spent 638µs within Convert::ASN1::asn_tag which was called 74 times, avg 9µs/call:
# 74 times (638µs+0s) by Convert::ASN1::parser::yylex at line 881 of Convert/ASN1/parser.pm, avg 9µs/call | ||||
| 395 | 74 | 98µs | my($class,$value) = @_; | ||
| 396 | |||||
| 397 | 74 | 60µs | die sprintf "Bad tag class 0x%x",$class | ||
| 398 | if $class & ~0xe0; | ||||
| 399 | |||||
| 400 | 74 | 486µs | unless ($value & ~0x1f or $value == 0x1f) { | ||
| 401 | return (($class & 0xe0) | $value); | ||||
| 402 | } | ||||
| 403 | |||||
| 404 | die sprintf "Tag value 0x%08x too big\n",$value | ||||
| 405 | if $value & 0xffe00000; | ||||
| 406 | |||||
| 407 | $class = ($class | 0x1f) & 0xff; | ||||
| 408 | |||||
| 409 | my @t = ($value & 0x7f); | ||||
| 410 | unshift @t, (0x80 | ($value & 0x7f)) while $value >>= 7; | ||||
| 411 | unpack("V",pack("C4",$class,@t,0,0)); | ||||
| 412 | } | ||||
| 413 | |||||
| 414 | |||||
| 415 | # spent 13.8ms (11.8+1.98) within Convert::ASN1::BEGIN@415 which was called:
# once (11.8ms+1.98ms) by Net::LDAP::BEGIN@12 at line 425 | ||||
| 416 | # When we have XS &_encode will be defined by the XS code | ||||
| 417 | # so will all the subs in these required packages | ||||
| 418 | 1 | 2µs | unless (defined &_encode) { | ||
| 419 | 1 | 107µs | require Convert::ASN1::_decode; | ||
| 420 | 1 | 119µs | require Convert::ASN1::_encode; | ||
| 421 | 1 | 85µs | require Convert::ASN1::IO; | ||
| 422 | } | ||||
| 423 | |||||
| 424 | 1 | 90µs | require Convert::ASN1::parser; | ||
| 425 | 1 | 196µs | 1 | 13.8ms | } # spent 13.8ms making 1 call to Convert::ASN1::BEGIN@415 |
| 426 | |||||
| 427 | sub AUTOLOAD { | ||||
| 428 | require Convert::ASN1::Debug if $AUTOLOAD =~ /dump/; | ||||
| 429 | goto &{$AUTOLOAD} if defined &{$AUTOLOAD}; | ||||
| 430 | require Carp; | ||||
| 431 | my $pkg = ref($_[0]) || ($_[0] =~ /^[\w\d]+(?:::[\w\d]+)*$/)[0]; | ||||
| 432 | if ($pkg and UNIVERSAL::isa($pkg, __PACKAGE__)) { # guess it was a method call | ||||
| 433 | $AUTOLOAD =~ s/.*:://; | ||||
| 434 | Carp::croak(sprintf q{Can't locate object method "%s" via package "%s"},$AUTOLOAD,$pkg); | ||||
| 435 | } | ||||
| 436 | else { | ||||
| 437 | Carp::croak(sprintf q{Undefined subroutine &%s called}, $AUTOLOAD); | ||||
| 438 | } | ||||
| 439 | } | ||||
| 440 | |||||
| 441 | sub DESTROY {} | ||||
| 442 | |||||
| 443 | sub error { $_[0]->{error} } | ||||
| 444 | 1 | 3µs | 1; | ||
# spent 5µs within Convert::ASN1::CORE:match which was called:
# once (5µs+0s) by Convert::ASN1::configure at line 117 |