2929#
3030
3131
32-
33-
3432module Net
3533
3634 module BER
@@ -52,14 +50,34 @@ def initialize
5250 end
5351 end
5452
53+ #--
54+ # This condenses our nicely self-documenting ASN hashes down
55+ # to an array for fast lookups.
56+ # Scoped to be called as a module method, but not intended for
57+ # user code to call.
58+ #
59+ def self . compile_syntax syn
60+ out = [ nil ] * 256
61+ syn . each { |tclass , tclasses |
62+ tagclass = { :universal => 0 , :application => 64 , :context_specific => 128 , :private => 192 } [ tclass ]
63+ tclasses . each { |codingtype , codings |
64+ encoding = { :primitive => 0 , :constructed => 32 } [ codingtype ]
65+ codings . each { |tag , objtype |
66+ out [ tagclass + encoding + tag ] = objtype
67+ }
68+ }
69+ }
70+ out
71+ end
72+
5573 # This module is for mixing into IO and IO-like objects.
5674 module BERParser
5775
5876 # The order of these follows the class-codes in BER.
5977 # Maybe this should have been a hash.
6078 TagClasses = [ :universal , :application , :context_specific , :private ]
6179
62- BuiltinSyntax = {
80+ BuiltinSyntax = BER . compile_syntax ( {
6381 :universal => {
6482 :primitive => {
6583 1 => :boolean ,
@@ -72,7 +90,7 @@ module BERParser
7290 17 => :array
7391 }
7492 }
75- }
93+ } )
7694
7795 #
7896 # read_ber
@@ -86,10 +104,10 @@ def read_ber syntax=nil
86104 #return nil if eof?
87105
88106 id = getc or return nil # don't trash this value, we'll use it later
89- tag = id & 31
90- tag < 31 or raise BerError . new ( "unsupported tag encoding: #{ id } " )
91- tagclass = TagClasses [ id >> 6 ]
92- encoding = ( id & 0x20 != 0 ) ? :constructed : :primitive
107+ # tag = id & 31
108+ # tag < 31 or raise BerError.new( "unsupported tag encoding: #{id}" )
109+ # tagclass = TagClasses[ id >> 6 ]
110+ # encoding = (id & 0x20 != 0) ? :constructed : :primitive
93111
94112 n = getc
95113 lengthlength , contentlength = if n <= 127
@@ -105,14 +123,17 @@ def read_ber syntax=nil
105123 newobj = read contentlength
106124
107125 # This exceptionally clever and clear bit of code is verrrry slow.
126+ =begin
108127 objtype = nil
109128 [syntax, BuiltinSyntax].each {|syn|
110129 if syn && (ot = syn[tagclass]) && (ot = ot[encoding]) && ot[tag]
111130 objtype = ot[tag]
112131 break
113132 end
114133 }
115-
134+ =end
135+ objtype = ( syntax && syntax [ id ] ) || BuiltinSyntax [ id ]
136+
116137=begin
117138 Replaced this case with if/else because Symbol#=== profiled surprisingly hot.
118139 obj = case objtype
@@ -164,7 +185,8 @@ def read_ber syntax=nil
164185 elsif objtype == :boolean
165186 newobj != "\000 "
166187 else
167- raise BerError . new ( "unsupported object type: class=#{ tagclass } , encoding=#{ encoding } , tag=#{ tag } " )
188+ #raise BerError.new( "unsupported object type: class=#{tagclass}, encoding=#{encoding}, tag=#{tag}" )
189+ raise BerError . new ( "unsupported object type: id=#{ id } " )
168190 end
169191
170192 # Add the identifier bits into the object if it's a String or an Array.
0 commit comments