11# -*- ruby encoding: utf-8 -*-
22##
3- # Ber extensions to the Fixnum class.
4- module Net ::BER ::Extensions ::Fixnum
3+ # BER extensions to the Integer class, affecting Fixnum and Bignum objects .
4+ module Net ::BER ::Extensions ::Integer
55 ##
6- # Converts the fixnum to BER format.
6+ # Converts the Integer to BER format.
77 def to_ber
88 "\002 #{ to_ber_internal } "
99 end
1010
1111 ##
12- # Converts the fixnum to BER enumerated format.
12+ # Converts the Integer to BER enumerated format.
1313 def to_ber_enumerated
1414 "\012 #{ to_ber_internal } "
1515 end
1616
1717 ##
18- # Converts the fixnum to BER length encodining format.
18+ # Converts the Integer to BER length encoding format.
1919 def to_ber_length_encoding
2020 if self <= 127
2121 [ self ] . pack ( 'C' )
@@ -33,34 +33,34 @@ def to_ber_application(tag)
3333 end
3434
3535 ##
36- # Used to BER-encode the length and content bytes of a Fixnum . Callers
36+ # Used to BER-encode the length and content bytes of an Integer . Callers
3737 # must prepend the tag byte for the contained value.
3838 def to_ber_internal
39- # CAUTION: Bit twiddling ahead. You might want to shield your eyes or
40- # something.
39+ # Compute the byte length, accounting for negative values requiring two's
40+ # complement.
41+ size = 1
42+ size += 1 until ( ( ( self < 0 ) ? ~self : self ) >> ( size * 8 ) ) . zero?
4143
42- # Looks for the first byte in the fixnum that is not all zeroes. It does
43- # this by masking one byte after another, checking the result for bits
44- # that are left on.
45- size = Net :: BER :: MAX_FIXNUM_SIZE
46- while size > 1
47- break if ( self & ( 0xff << ( size - 1 ) * 8 ) ) > 0
48- size - = 1
44+ # Padding for positive, negative values. See section 8.5 of ITU-T X.690:
45+ # http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
46+
47+ # For positive integers, if most significant bit in an octet is set to one,
48+ # pad the result (otherwise it's decoded as a negative value).
49+ if self > 0 && ( self & ( 0x80 << ( size - 1 ) * 8 ) ) > 0
50+ size + = 1
4951 end
5052
51- # for positive integers, if most significant bit in an octet is set to one,
52- # pad the result (otherwise it's decoded as a negative value)
53- # See section 8.5 of ITU-T X.690:
54- # http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
55- if self > 0 && ( self & ( 0b10000000 << ( size - 1 ) * 8 ) ) > 0
53+ # And for negative integers, pad if the most significant bit in the octet
54+ # is not set to one (othwerise, it's decoded as positive value).
55+ if self < 0 && ( self & ( 0x80 << ( size - 1 ) * 8 ) ) == 0
5656 size += 1
5757 end
5858
59- # Store the size of the fixnum in the result
59+ # Store the size of the Integer in the result
6060 result = [ size ]
6161
6262 # Appends bytes to result, starting with higher orders first. Extraction
63- # of bytes is done by right shifting the original fixnum by an amount
63+ # of bytes is done by right shifting the original Integer by an amount
6464 # and then masking that with 0xff.
6565 while size > 0
6666 # right shift size - 1 bytes, mask with 0xff
0 commit comments