You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

integer.py 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #
  2. # This file is part of pyasn1 software.
  3. #
  4. # Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
  5. # License: http://snmplabs.com/pyasn1/license.html
  6. #
  7. import sys
  8. try:
  9. import platform
  10. implementation = platform.python_implementation()
  11. except (ImportError, AttributeError):
  12. implementation = 'CPython'
  13. from pyasn1.compat.octets import oct2int, null, ensureString
  14. if sys.version_info[0:2] < (3, 2) or implementation != 'CPython':
  15. from binascii import a2b_hex, b2a_hex
  16. if sys.version_info[0] > 2:
  17. long = int
  18. def from_bytes(octets, signed=False):
  19. if not octets:
  20. return 0
  21. value = long(b2a_hex(ensureString(octets)), 16)
  22. if signed and oct2int(octets[0]) & 0x80:
  23. return value - (1 << len(octets) * 8)
  24. return value
  25. def to_bytes(value, signed=False, length=0):
  26. if value < 0:
  27. if signed:
  28. bits = bitLength(value)
  29. # two's complement form
  30. maxValue = 1 << bits
  31. valueToEncode = (value + maxValue) % maxValue
  32. else:
  33. raise OverflowError('can\'t convert negative int to unsigned')
  34. elif value == 0 and length == 0:
  35. return null
  36. else:
  37. bits = 0
  38. valueToEncode = value
  39. hexValue = hex(valueToEncode)[2:]
  40. if hexValue.endswith('L'):
  41. hexValue = hexValue[:-1]
  42. if len(hexValue) & 1:
  43. hexValue = '0' + hexValue
  44. # padding may be needed for two's complement encoding
  45. if value != valueToEncode or length:
  46. hexLength = len(hexValue) * 4
  47. padLength = max(length, bits)
  48. if padLength > hexLength:
  49. hexValue = '00' * ((padLength - hexLength - 1) // 8 + 1) + hexValue
  50. elif length and hexLength - length > 7:
  51. raise OverflowError('int too big to convert')
  52. firstOctet = int(hexValue[:2], 16)
  53. if signed:
  54. if firstOctet & 0x80:
  55. if value >= 0:
  56. hexValue = '00' + hexValue
  57. elif value < 0:
  58. hexValue = 'ff' + hexValue
  59. octets_value = a2b_hex(hexValue)
  60. return octets_value
  61. def bitLength(number):
  62. # bits in unsigned number
  63. hexValue = hex(abs(number))
  64. bits = len(hexValue) - 2
  65. if hexValue.endswith('L'):
  66. bits -= 1
  67. if bits & 1:
  68. bits += 1
  69. bits *= 4
  70. # TODO: strip lhs zeros
  71. return bits
  72. else:
  73. def from_bytes(octets, signed=False):
  74. return int.from_bytes(bytes(octets), 'big', signed=signed)
  75. def to_bytes(value, signed=False, length=0):
  76. length = max(value.bit_length(), length)
  77. if signed and length % 8 == 0:
  78. length += 1
  79. return value.to_bytes(length // 8 + (length % 8 and 1 or 0), 'big', signed=signed)
  80. def bitLength(number):
  81. return int(number).bit_length()