File: integer.rb

package info (click to toggle)
ruby-net-ldap 0.20.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 648 kB
  • sloc: ruby: 4,671; sh: 54; makefile: 4
file content (74 lines) | stat: -rw-r--r-- 2,241 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# -*- ruby encoding: utf-8 -*-
##
# BER extensions to the Integer class, affecting Fixnum and Bignum objects.
module Net::BER::Extensions::Integer
  ##
  # Converts the Integer to BER format.
  def to_ber
    "\002#{to_ber_internal}"
  end

  ##
  # Converts the Integer to BER enumerated format.
  def to_ber_enumerated
    "\012#{to_ber_internal}"
  end

  ##
  # Converts the Integer to BER length encoding format.
  def to_ber_length_encoding
    if self <= 127
      [self].pack('C')
    else
      i = [self].pack('N').sub(/^[\0]+/, "")
      [0x80 + i.length].pack('C') + i
    end
  end

  ##
  # Generate a BER-encoding for an application-defined INTEGER. Examples of
  # such integers are SNMP's Counter, Gauge, and TimeTick types.
  def to_ber_application(tag)
    [0x40 + tag].pack("C") + to_ber_internal
  end

  ##
  # Used to BER-encode the length and content bytes of an Integer. Callers
  # must prepend the tag byte for the contained value.
  def to_ber_internal
    # Compute the byte length, accounting for negative values requiring two's
    # complement.
    size  = 1
    size += 1 until (((self < 0) ? ~self : self) >> (size * 8)).zero?

    # Padding for positive, negative values. See section 8.5 of ITU-T X.690:
    # http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf

    # For positive integers, if most significant bit in an octet is set to one,
    # pad the result (otherwise it's decoded as a negative value).
    if self > 0 && (self & (0x80 << (size - 1) * 8)) > 0
      size += 1
    end

    # And for negative integers, pad if the most significant bit in the octet
    # is not set to one (othwerise, it's decoded as positive value).
    if self < 0 && (self & (0x80 << (size - 1) * 8)) == 0
      size += 1
    end

    # Store the size of the Integer in the result
    result = [size]

    # Appends bytes to result, starting with higher orders first. Extraction
    # of bytes is done by right shifting the original Integer by an amount
    # and then masking that with 0xff.
    while size > 0
      # right shift size - 1 bytes, mask with 0xff
      result << ((self >> ((size - 1) * 8)) & 0xff)
      size -= 1
    end

    result.pack('C*')
  end
  private :to_ber_internal
end