aboutsummaryrefslogtreecommitdiffstats
path: root/src/shorturls/baseconv.py
diff options
context:
space:
mode:
authorBen Firshman2014-09-22 02:18:09 +0200
committerBen Firshman2014-09-22 02:18:09 +0200
commit47dcc785c2d6bcbbcf0cbaabdd5d8c825bc97e9c (patch)
treef184d0ff8da4d2644ae4faed3bddcb9e5790b596 /src/shorturls/baseconv.py
parent967f4ddab7bb68bc1cbd10a30658c65fd67c9acb (diff)
parentab5312e7c035e76521140382b47113bcf50acbcf (diff)
downloaddjango-shorturls-47dcc785c2d6bcbbcf0cbaabdd5d8c825bc97e9c.tar.bz2
Merge pull request #8 from bfirsh/crockford-base32
Add Crockford's base32 and performance improvements
Diffstat (limited to 'src/shorturls/baseconv.py')
-rw-r--r--src/shorturls/baseconv.py86
1 files changed, 57 insertions, 29 deletions
diff --git a/src/shorturls/baseconv.py b/src/shorturls/baseconv.py
index 1e22ed1..1b4fd15 100644
--- a/src/shorturls/baseconv.py
+++ b/src/shorturls/baseconv.py
@@ -13,46 +13,74 @@ Sample usage:
"""
class BaseConverter(object):
- decimal_digits = "0123456789"
+ decode_mapping = {}
def __init__(self, digits):
self.digits = digits
+ self.length = len(digits)
def from_decimal(self, i):
- return self.convert(i, self.decimal_digits, self.digits)
+ if i < 0:
+ i, neg = -i, 1
+ else:
+ neg = 0
+ enc = ''
+ while i >= self.length:
+ i, mod = divmod(i, self.length)
+ enc = self.digits[mod] + enc
+ enc = self.digits[i] + enc
+ if neg:
+ enc = '-' + enc
+ return enc
def to_decimal(self, s):
- return int(self.convert(s, self.digits, self.decimal_digits))
-
- def convert(number, fromdigits, todigits):
- # Based on http://code.activestate.com/recipes/111286/
- if str(number)[0] == '-':
- number = str(number)[1:]
- neg = 1
+ if self.decode_mapping:
+ new = ''
+ for digit in s:
+ if digit in self.decode_mapping:
+ new += self.decode_mapping[digit]
+ else:
+ new += digit
+ s = new
+ if str(s)[0] == '-':
+ s, neg = str(s)[1:], 1
else:
neg = 0
-
- # make an integer out of the number
- x = 0
- for digit in str(number):
- x = x * len(fromdigits) + fromdigits.index(digit)
+ decoded = 0
+ multi = 1
+ while len(s) > 0:
+ decoded += multi * self.digits.index(s[-1:])
+ multi = multi * self.length
+ s = s[:-1]
+ if neg:
+ decoded = -decoded
+ return decoded
- # create the result in base 'len(todigits)'
- if x == 0:
- res = todigits[0]
- else:
- res = ""
- while x > 0:
- digit = x % len(todigits)
- res = todigits[digit] + res
- x = int(x / len(todigits))
- if neg:
- res = '-' + res
- return res
- convert = staticmethod(convert)
-
bin = BaseConverter('01')
hexconv = BaseConverter('0123456789ABCDEF')
base62 = BaseConverter(
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz'
-) \ No newline at end of file
+)
+
+class Base32Converter(BaseConverter):
+ """
+ http://www.crockford.com/wrmg/base32.html
+ """
+ decode_mapping = {
+ 'o': '0',
+ 'i': '1',
+ 'l': '1',
+ }
+
+ def __init__(self):
+ super(Base32Converter, self).__init__('0123456789abcdefghjkmnpqrstvwxyz')
+
+ def to_decimal(self, s):
+ return super(Base32Converter, self).to_decimal(s.lower())
+
+base32 = Base32Converter()
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
+