python/base36.py
changeset 18 77fe8d4bcbd0
parent 13 68bb6da58cc2
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/python/base36.py	Wed Jun 09 15:12:43 2010 -0400
     1.3 @@ -0,0 +1,59 @@
     1.4 +"""
     1.5 +Base36 Encoder/Decoder
     1.6 +by Mike Crute (mcrute@gmail.com) on August 26, 2008
     1.7 +This code has been placed in the public domain.
     1.8 +
     1.9 +This is just a simple module to do base36 encoding and decoding. Theoretically
    1.10 +you could use this for any base < 2 <= 36 && base != 32 but I only really need 
    1.11 +to have base36 so its an exercise for the reader to implement other base 
    1.12 +conversions.
    1.13 +
    1.14 +This won't work for base32 at least not if you want your output to work with other
    1.15 +base32 decoders because RFC4648 skips 0 and 1 (2-7A-Z) and this module doesn't
    1.16 +account for that. Bah...
    1.17 +
    1.18 +The only reason I wrote this is because the other implementations of base
    1.19 +conversion relied upon hard coded lists of characters and that really 
    1.20 +bothered me, plus didn't quite give me the flexibility I was looking for.
    1.21 +"""
    1.22 +
    1.23 +def _codec(str_in, base_from=36, base_to=10):
    1.24 +    """Convert a number to/from a base less than or equal to 36.
    1.25 +    Converts a string or number to or from a base without using static
    1.26 +    lookup tables.
    1.27 +    """
    1.28 +    # Some ASCII Codes
    1.29 +    ASCII = { "0": 48, "9": 57, "A": 65, "Z": 90 }
    1.30 +    
    1.31 +    # There are 8 characters between 9 and A
    1.32 +    from_digits = [chr(x) for x in range(ASCII["0"], ASCII["9"] + 8 + base_from) 
    1.33 +                            if (x >= ASCII["0"] and x <= ASCII["9"]) or 
    1.34 +                               (x >= ASCII["A"] and x <= ASCII["Z"])][:base_from]
    1.35 +                               
    1.36 +    to_digits = [chr(x) for x in range(ASCII["0"], ASCII["9"] + 8 + base_to) 
    1.37 +                            if (x >= ASCII["0"] and x <= ASCII["9"]) or 
    1.38 +                               (x >= ASCII["A"] and x <= ASCII["Z"])][:base_to]
    1.39 +    
    1.40 +    x = long(0)
    1.41 +    for digit in str(str_in).upper():
    1.42 +        x = x * len(from_digits) + from_digits.index(digit)
    1.43 +
    1.44 +    result = ""
    1.45 +    # This is going to assemble our number in reverse order
    1.46 +    # so we'll have to fix it before we return it
    1.47 +    while x > 0:
    1.48 +        result += to_digits[x % len(to_digits)]
    1.49 +        x /= len(to_digits)
    1.50 +        
    1.51 +    return result[::-1]
    1.52 +    
    1.53 +    
    1.54 +def base36encode(str_in):
    1.55 +    """Base36 encode a base10 number.
    1.56 +    """
    1.57 +    return _codec(str_in, 10, 36)
    1.58 +    
    1.59 +def base36encode(str_in):
    1.60 +    """Get a base10 number for a base36 number.
    1.61 +    """
    1.62 +    return long(_codec(str_in, 36, 10))
    1.63 \ No newline at end of file