base91.py 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. # Base91 encode/decode
  2. #
  3. # Copyright (c) 2012 Adrien Beraud
  4. # All rights reserved.
  5. #
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions are met:
  8. #
  9. # * Redistributions of source code must retain the above copyright notice,
  10. # this list of conditions and the following disclaimer.
  11. # * Redistributions in binary form must reproduce the above copyright notice,
  12. # this list of conditions and the following disclaimer in the documentation
  13. # and/or other materials provided with the distribution.
  14. # * Neither the name of Adrien Beraud, Wisdom Vibes Pte. Ltd., nor the names
  15. # of its contributors may be used to endorse or promote products derived
  16. # from this software without specific prior written permission.
  17. #
  18. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  19. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  22. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  24. # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25. # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  27. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. #
  29. import struct
  30. base91_alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
  31. 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  32. 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
  33. 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
  34. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '#', '$',
  35. '%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=',
  36. '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"']
  37. decode_table = dict((v,k) for k,v in enumerate(base91_alphabet))
  38. def decode(encoded_str):
  39. ''' Decode Base91 string to a bytearray '''
  40. v = -1
  41. b = 0
  42. n = 0
  43. out = bytearray()
  44. for strletter in encoded_str:
  45. if not strletter in decode_table:
  46. continue
  47. c = decode_table[strletter]
  48. if(v < 0):
  49. v = c
  50. else:
  51. v += c*91
  52. b |= v << n
  53. n += 13 if (v & 8191)>88 else 14
  54. while True:
  55. out += struct.pack('B', b&255)
  56. b >>= 8
  57. n -= 8
  58. if not n>7:
  59. break
  60. v = -1
  61. if v+1:
  62. out += struct.pack('B', (b | v << n) & 255 )
  63. return out
  64. def encode(bindata):
  65. ''' Encode a bytearray to a Base91 string '''
  66. l = len(bindata)
  67. b = 0
  68. n = 0
  69. out = ''
  70. for byte in bindata:
  71. b |= struct.unpack('B', byte)[0] << n
  72. n += 8
  73. if n>13:
  74. v = b & 8191
  75. if v > 88:
  76. b >>= 13
  77. n -= 13
  78. else:
  79. v = b & 16383
  80. b >>= 14
  81. n -= 14
  82. out += base91_alphabet[v % 91] + base91_alphabet[v / 91]
  83. if n:
  84. out += base91_alphabet[b % 91]
  85. if n>7 or b>90:
  86. out += base91_alphabet[b / 91]
  87. return out