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.

baseconv.py 2.9KB

5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. # Copyright (c) 2010 Guilherme Gondim. All rights reserved.
  2. # Copyright (c) 2009 Simon Willison. All rights reserved.
  3. # Copyright (c) 2002 Drew Perttula. All rights reserved.
  4. #
  5. # License:
  6. # Python Software Foundation License version 2
  7. #
  8. # See the file "LICENSE" for terms & conditions for usage, and a DISCLAIMER OF
  9. # ALL WARRANTIES.
  10. #
  11. # This Baseconv distribution contains no GNU General Public Licensed (GPLed)
  12. # code so it may be used in proprietary projects just like prior ``baseconv``
  13. # distributions.
  14. #
  15. # All trademarks referenced herein are property of their respective holders.
  16. #
  17. """
  18. Convert numbers from base 10 integers to base X strings and back again.
  19. Sample usage::
  20. >>> base20 = BaseConverter('0123456789abcdefghij')
  21. >>> base20.encode(1234)
  22. '31e'
  23. >>> base20.decode('31e')
  24. 1234
  25. >>> base20.encode(-1234)
  26. '-31e'
  27. >>> base20.decode('-31e')
  28. -1234
  29. >>> base11 = BaseConverter('0123456789-', sign='$')
  30. >>> base11.encode('$1234')
  31. '$-22'
  32. >>> base11.decode('$-22')
  33. '$1234'
  34. """
  35. BASE2_ALPHABET = '01'
  36. BASE16_ALPHABET = '0123456789ABCDEF'
  37. BASE56_ALPHABET = '23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz'
  38. BASE36_ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz'
  39. BASE62_ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
  40. BASE64_ALPHABET = BASE62_ALPHABET + '-_'
  41. class BaseConverter:
  42. decimal_digits = '0123456789'
  43. def __init__(self, digits, sign='-'):
  44. self.sign = sign
  45. self.digits = digits
  46. if sign in self.digits:
  47. raise ValueError('Sign character found in converter base digits.')
  48. def __repr__(self):
  49. return "<%s: base%s (%s)>" % (self.__class__.__name__, len(self.digits), self.digits)
  50. def encode(self, i):
  51. neg, value = self.convert(i, self.decimal_digits, self.digits, '-')
  52. if neg:
  53. return self.sign + value
  54. return value
  55. def decode(self, s):
  56. neg, value = self.convert(s, self.digits, self.decimal_digits, self.sign)
  57. if neg:
  58. value = '-' + value
  59. return int(value)
  60. def convert(self, number, from_digits, to_digits, sign):
  61. if str(number)[0] == sign:
  62. number = str(number)[1:]
  63. neg = 1
  64. else:
  65. neg = 0
  66. # make an integer out of the number
  67. x = 0
  68. for digit in str(number):
  69. x = x * len(from_digits) + from_digits.index(digit)
  70. # create the result in base 'len(to_digits)'
  71. if x == 0:
  72. res = to_digits[0]
  73. else:
  74. res = ''
  75. while x > 0:
  76. digit = x % len(to_digits)
  77. res = to_digits[digit] + res
  78. x = int(x // len(to_digits))
  79. return neg, res
  80. base2 = BaseConverter(BASE2_ALPHABET)
  81. base16 = BaseConverter(BASE16_ALPHABET)
  82. base36 = BaseConverter(BASE36_ALPHABET)
  83. base56 = BaseConverter(BASE56_ALPHABET)
  84. base62 = BaseConverter(BASE62_ALPHABET)
  85. base64 = BaseConverter(BASE64_ALPHABET, sign='$')