Paste number 72815: pure python base85

Index of paste annotations: 1

Paste number 72815: pure python base85
Pasted by: brendan
When:1 year, 1 month ago
Share:Tweet this! | http://paste.lisp.org/+1K6N
Channel:#mercurial
Paste contents:
Raw Source | XML | Display As
# base85.py: pure python base85 codec
#
# Copyright (C) 2008 Brendan Cully <brendan@kublai.com>
#
# This software may be used and distributed according to the terms of
# the GNU General Public License, incorporated herein by reference.

import struct

_b85chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
            "abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"
_b85dec = {}

def _mkb85dec():
    for i in range(len(_b85chars)):
        _b85dec[_b85chars[i]] = i

def b85encode(text, pad=False):
    """encode text in base85 format"""
    l = len(text)
    r = l % 4
    if r:
        text += '\0' * (4 - r)
    longs = len(text) >> 2
    out = []
    words = struct.unpack('>' + 'L' * longs, text[0:longs*4])
    for word in words:
        rems = [0, 0, 0, 0, 0]
        for i in range(4, -1, -1):
            rems[i] = _b85chars[word % 85]
            word /= 85
        out.extend(rems)

    out = ''.join(out)
    if pad:
        return out

    # Trim padding
    olen = l % 4
    if olen:
        olen += 1
    olen += l / 4 * 5
    return out[0:olen]

def b85decode(text):
    """decode base85-encoded text"""
    if not _b85dec:
        _mkb85dec()

    l = len(text)
    out = []
    for i in range(0, len(text), 5):
        chunk = text[i:i+5]
        acc = 0
        for j in range(len(chunk)):
            try:
                acc = acc * 85 + _b85dec[chunk[j]]
            except KeyError:
                raise TypeError('Bad base85 character at byte %d' % (i + j))
        if acc > 4294967295:
            raise OverflowError('Base85 overflow in hunk starting at byte %d' % i)
        out.append(acc)

    # Pad final chunk if necessary
    cl = l % 5
    if cl:
        acc *= 85 ** (5 - cl)
        if cl > 1:
            acc += 0xffffff >> (cl - 2) * 8
        out[-1] = acc

    out = struct.pack('>' + 'L' * ((l + 4) / 5), *out)
    if cl:
        out = out[:-(5 - cl)]

    return out

Annotations for this paste:

Annotation number 1: performance difference
Pasted by: brendan
When:1 year, 1 month ago
Share:Tweet this! | http://paste.lisp.org/+1K6N/1
Paste contents:
Raw Source | Display As
def perf85(ui, repo, f):
    text = open(f).read()
    import mercurial.base85
    def d():
        mercurial.base85.b85decode(mercurial.base85.b85encode(text))
    timer(d)

# native code
% hg perf85 mercurial/commands.py
! wall 0.001472 comb 0.000000 user 0.000000 sys 0.000000 (best of 2020)

# python version
% hg perf85 mercurial/commands.py          ~/dev/hg/crew
! wall 0.232690 comb 0.240000 user 0.230000 sys 0.010000 (best of 43)

Colorize as:
Show Line Numbers
Index of paste annotations: 1

Lisppaste pastes can be made by anyone at any time. Imagine a fearsomely comprehensive disclaimer of liability. Now fear, comprehensively.