mercurial/pure/base85.py
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
Tue, 06 Jan 2015 23:46:18 +0900
changeset 23742 3a4d8a6ce432
parent 16598 20a9d823f242
child 27334 9007f697e8ef
permissions -rw-r--r--
revset: introduce new operator "##" to concatenate strings/symbols at runtime Before this patch, there is no way to concatenate strings at runtime. For example, to search for the issue ID "1234" in descriptions against all of "issue 1234", "issue:1234", issue1234" and "bug(1234)" patterns, the revset below should be written fully from scratch for each issue ID. grep(r"\bissue[ :]?1234\b|\bbug\(1234\)") This patch introduces new infix operator "##" to concatenate strings/symbols at runtime. Operator symbol "##" comes from the same one of C pre-processor. This concatenation allows parametrizing a part of strings in revset queries. In the case of example above, the definition of the revset alias using operator "##" below can search issue ID "1234" in complicated patterns by "issue(1234)" simply: issue($1) = grep(r"\bissue[ :]?" ## $1 ## r"\b|\bbug\(" ## $1 ## r"\)") "##" operator does: - concatenate not only strings but also symbols into the string Exact distinction between strings and symbols seems not to be convenience, because it is tiresome for users (and "revset.getstring" treats both similarly) For example of revset alias "issue()", "issue(1234)" is easier than "issue('1234')". - have higher priority than any other prefix, infix and postfix operators (like as "##" of C pre-processor) This patch (re-)assigns the priority 20 to "##", and 21 to "(", because priority 19 is already assigned to "-" as prefix "negate".
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
7701
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
     1
# base85.py: pure python base85 codec
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
     2
#
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
     3
# Copyright (C) 2009 Brendan Cully <brendan@kublai.com>
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
     4
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 7881
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9029
diff changeset
     6
# GNU General Public License version 2 or any later version.
7701
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
     7
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
     8
import struct
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
     9
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    10
_b85chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    11
            "abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"
7835
2505e9f84153 Optimization of pure.base85.b85encode
Mads Kiilerich <mads@kiilerich.com>
parents: 7701
diff changeset
    12
_b85chars2 = [(a + b) for a in _b85chars for b in _b85chars]
7701
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    13
_b85dec = {}
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    14
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    15
def _mkb85dec():
8632
9e055cfdd620 replace "i in range(len(xs))" with "i, x in enumerate(xs)"
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
    16
    for i, c in enumerate(_b85chars):
9e055cfdd620 replace "i in range(len(xs))" with "i, x in enumerate(xs)"
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
    17
        _b85dec[c] = i
7701
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    18
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    19
def b85encode(text, pad=False):
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    20
    """encode text in base85 format"""
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    21
    l = len(text)
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    22
    r = l % 4
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    23
    if r:
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    24
        text += '\0' * (4 - r)
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    25
    longs = len(text) >> 2
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    26
    words = struct.unpack('>%dL' % (longs), text)
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    27
9029
0001e49f1c11 compat: use // for integer division
Alejandro Santos <alejolp@alejolp.com>
parents: 8632
diff changeset
    28
    out = ''.join(_b85chars[(word // 52200625) % 85] +
0001e49f1c11 compat: use // for integer division
Alejandro Santos <alejolp@alejolp.com>
parents: 8632
diff changeset
    29
                  _b85chars2[(word // 7225) % 7225] +
7835
2505e9f84153 Optimization of pure.base85.b85encode
Mads Kiilerich <mads@kiilerich.com>
parents: 7701
diff changeset
    30
                  _b85chars2[word % 7225]
2505e9f84153 Optimization of pure.base85.b85encode
Mads Kiilerich <mads@kiilerich.com>
parents: 7701
diff changeset
    31
                  for word in words)
7701
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    32
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    33
    if pad:
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    34
        return out
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    35
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    36
    # Trim padding
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    37
    olen = l % 4
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    38
    if olen:
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    39
        olen += 1
9029
0001e49f1c11 compat: use // for integer division
Alejandro Santos <alejolp@alejolp.com>
parents: 8632
diff changeset
    40
    olen += l // 4 * 5
7701
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    41
    return out[:olen]
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    42
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    43
def b85decode(text):
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    44
    """decode base85-encoded text"""
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    45
    if not _b85dec:
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    46
        _mkb85dec()
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    47
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    48
    l = len(text)
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    49
    out = []
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    50
    for i in range(0, len(text), 5):
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
    51
        chunk = text[i:i + 5]
7701
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    52
        acc = 0
8632
9e055cfdd620 replace "i in range(len(xs))" with "i, x in enumerate(xs)"
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
    53
        for j, c in enumerate(chunk):
7701
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    54
            try:
8632
9e055cfdd620 replace "i in range(len(xs))" with "i, x in enumerate(xs)"
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
    55
                acc = acc * 85 + _b85dec[c]
7701
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    56
            except KeyError:
16598
20a9d823f242 pure/base85: align exception type/msg on base85.c
Patrick Mezard <patrick@mezard.eu>
parents: 10282
diff changeset
    57
                raise ValueError('bad base85 character at position %d'
20a9d823f242 pure/base85: align exception type/msg on base85.c
Patrick Mezard <patrick@mezard.eu>
parents: 10282
diff changeset
    58
                                 % (i + j))
7701
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    59
        if acc > 4294967295:
16598
20a9d823f242 pure/base85: align exception type/msg on base85.c
Patrick Mezard <patrick@mezard.eu>
parents: 10282
diff changeset
    60
            raise ValueError('Base85 overflow in hunk starting at byte %d' % i)
7701
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    61
        out.append(acc)
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    62
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    63
    # Pad final chunk if necessary
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    64
    cl = l % 5
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    65
    if cl:
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    66
        acc *= 85 ** (5 - cl)
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    67
        if cl > 1:
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    68
            acc += 0xffffff >> (cl - 2) * 8
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    69
        out[-1] = acc
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    70
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    71
    out = struct.pack('>%dL' % (len(out)), *out)
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    72
    if cl:
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    73
        out = out[:-(5 - cl)]
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    74
4bdead043d8d Pure python base85 fallback
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
    75
    return out