70: def read_ber syntax=nil
71: return nil if eof?
72:
73: id = getc
74: tag = id & 31
75: tag < 31 or raise BerError.new( "unsupported tag encoding: #{id}" )
76: tagclass = TagClasses[ id >> 6 ]
77: encoding = (id & 0x20 != 0) ? :constructed : :primitive
78:
79: n = getc
80: lengthlength,contentlength = if n <= 127
81: [1,n]
82: else
83: j = (0...(n & 127)).inject(0) {|mem,x| mem = (mem << 8) + getc}
84: [1 + (n & 127), j]
85: end
86:
87: newobj = read contentlength
88:
89: objtype = nil
90: [syntax, BuiltinSyntax].each {|syn|
91: if syn && (ot = syn[tagclass]) && (ot = ot[encoding]) && ot[tag]
92: objtype = ot[tag]
93: break
94: end
95: }
96:
97: obj = case objtype
98: when :boolean
99: newobj != "\000"
100: when :string
101: (newobj || "").dup
102: when :integer
103: j = 0
104: newobj.each_byte {|b| j = (j << 8) + b}
105: j
106: when :array
107: seq = []
108: sio = StringIO.new( newobj || "" )
109:
110:
111:
112: while (e = sio.read_ber(syntax)) != nil
113: seq << e
114: end
115: seq
116: else
117: raise BerError.new( "unsupported object type: class=#{tagclass}, encoding=#{encoding}, tag=#{tag}" )
118: end
119:
120:
121:
122: obj and ([String,Array].include? obj.class) and obj.instance_eval "def ber_identifier; #{id}; end"
123: obj
124:
125: end