]> granicus.if.org Git - python/commitdiff
Speed up base64.urlsafe_{en,de}code().
authorGuido van Rossum <guido@python.org>
Fri, 22 Jun 2012 22:16:09 +0000 (15:16 -0700)
committerGuido van Rossum <guido@python.org>
Fri, 22 Jun 2012 22:16:09 +0000 (15:16 -0700)
Lib/base64.py
Misc/NEWS

index edcc4bea601131005a554c0cc43b03dad0308da6..4042f004fd9d03e7a87be5a9d003d790efb21631 100755 (executable)
@@ -40,14 +40,6 @@ def _bytes_from_decode_data(s):
     else:
         raise TypeError("argument should be bytes or ASCII string, not %s" % s.__class__.__name__)
 
-def _translate(s, altchars):
-    if not isinstance(s, bytes_types):
-        raise TypeError("expected bytes, not %s" % s.__class__.__name__)
-    translation = bytearray(range(256))
-    for k, v in altchars.items():
-        translation[ord(k)] = v[0]
-    return s.translate(translation)
-
 
 
 # Base64 encoding/decoding uses binascii
@@ -71,7 +63,7 @@ def b64encode(s, altchars=None):
             raise TypeError("expected bytes, not %s"
                             % altchars.__class__.__name__)
         assert len(altchars) == 2, repr(altchars)
-        return _translate(encoded, {'+': altchars[0:1], '/': altchars[1:2]})
+        return encoded.translate(bytes.maketrans(b'+/', altchars))
     return encoded
 
 
@@ -93,7 +85,7 @@ def b64decode(s, altchars=None, validate=False):
     if altchars is not None:
         altchars = _bytes_from_decode_data(altchars)
         assert len(altchars) == 2, repr(altchars)
-        s = _translate(s, {chr(altchars[0]): b'+', chr(altchars[1]): b'/'})
+        s = s.translate(bytes.maketrans(altchars, b'+/'))
     if validate and not re.match(b'^[A-Za-z0-9+/]*={0,2}$', s):
         raise binascii.Error('Non-base64 digit found')
     return binascii.a2b_base64(s)
@@ -116,6 +108,10 @@ def standard_b64decode(s):
     """
     return b64decode(s)
 
+
+_urlsafe_encode_translation = bytes.maketrans(b'+/', b'-_')
+_urlsafe_decode_translation = bytes.maketrans(b'-_', b'+/')
+
 def urlsafe_b64encode(s):
     """Encode a byte string using a url-safe Base64 alphabet.
 
@@ -123,7 +119,7 @@ def urlsafe_b64encode(s):
     returned.  The alphabet uses '-' instead of '+' and '_' instead of
     '/'.
     """
-    return b64encode(s, b'-_')
+    return b64encode(s).translate(_urlsafe_encode_translation)
 
 def urlsafe_b64decode(s):
     """Decode a byte string encoded with the standard Base64 alphabet.
@@ -135,7 +131,9 @@ def urlsafe_b64decode(s):
 
     The alphabet uses '-' instead of '+' and '_' instead of '/'.
     """
-    return b64decode(s, b'-_')
+    s = _bytes_from_decode_data(s)
+    s = s.translate(_urlsafe_decode_translation)
+    return b64decode(s)
 
 
 
@@ -228,7 +226,7 @@ def b32decode(s, casefold=False, map01=None):
     if map01 is not None:
         map01 = _bytes_from_decode_data(map01)
         assert len(map01) == 1, repr(map01)
-        s = _translate(s, {b'0': b'O', b'1': map01})
+        s = s.translate(bytes.maketrans(b'01', b'O' + map01))
     if casefold:
         s = s.upper()
     # Strip off pad characters from the right.  We need to count the pad
index af1e26c3dbe47c317f87ba7150f3b472f94f5e83..70258dcd054b3b9b78a862d5203dfdaa1e107808 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -40,6 +40,8 @@ Core and Builtins
 Library
 -------
 
+- Issue: #15138: base64.urlsafe_{en,de}code() are now 3-4x faster.
+
 - Issue #9527: datetime.astimezone() method will now supply a class
   timezone instance corresponding to the system local timezone when
   called with no arguments.