/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/util/bencode.py

  • Committer: John Arbash Meinel
  • Date: 2009-04-21 23:54:16 UTC
  • mto: (4300.1.7 groupcompress_info)
  • mto: This revision was merged to the branch mainline in revision 4301.
  • Revision ID: john@arbash-meinel.com-20090421235416-f0cz6ilf5cufbugi
Fix bug #364900, properly remove the 64kB that was just encoded in the copy.
Also, stop supporting None as a copy length in 'encode_copy_instruction'.
It was only used by the test suite, and it is good to pull that sort of thing out of
production code. (Besides, setting the copy to 64kB has the same effect.)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# bencode structured encoding
 
2
#
 
3
# Written by Petru Paler
 
4
#
 
5
# Permission is hereby granted, free of charge, to any person
 
6
# obtaining a copy of this software and associated documentation files
 
7
# (the "Software"), to deal in the Software without restriction,
 
8
# including without limitation the rights to use, copy, modify, merge,
 
9
# publish, distribute, sublicense, and/or sell copies of the Software,
 
10
# and to permit persons to whom the Software is furnished to do so,
 
11
# subject to the following conditions:
 
12
#
 
13
# The above copyright notice and this permission notice shall be
 
14
# included in all copies or substantial portions of the Software.
 
15
#
 
16
# Modifications copyright (C) 2008 Canonical Ltd
 
17
 
 
18
class BDecoder(object):
 
19
 
 
20
    def __init__(self, yield_tuples=False):
 
21
        """Constructor.
 
22
 
 
23
        :param yield_tuples: if true, decode "l" elements as tuples rather than
 
24
            lists.
 
25
        """
 
26
        self.yield_tuples = yield_tuples
 
27
        decode_func = {}
 
28
        decode_func['l'] = self.decode_list
 
29
        decode_func['d'] = self.decode_dict
 
30
        decode_func['i'] = self.decode_int
 
31
        decode_func['0'] = self.decode_string
 
32
        decode_func['1'] = self.decode_string
 
33
        decode_func['2'] = self.decode_string
 
34
        decode_func['3'] = self.decode_string
 
35
        decode_func['4'] = self.decode_string
 
36
        decode_func['5'] = self.decode_string
 
37
        decode_func['6'] = self.decode_string
 
38
        decode_func['7'] = self.decode_string
 
39
        decode_func['8'] = self.decode_string
 
40
        decode_func['9'] = self.decode_string
 
41
        self.decode_func = decode_func
 
42
 
 
43
    def decode_int(self, x, f):
 
44
        f += 1
 
45
        newf = x.index('e', f)
 
46
        try:
 
47
            n = int(x[f:newf])
 
48
        except (OverflowError, ValueError):
 
49
            n = long(x[f:newf])
 
50
        if x[f] == '-':
 
51
            if x[f + 1] == '0':
 
52
                raise ValueError
 
53
        elif x[f] == '0' and newf != f+1:
 
54
            raise ValueError
 
55
        return (n, newf+1)
 
56
 
 
57
    def decode_string(self, x, f):
 
58
        colon = x.index(':', f)
 
59
        try:
 
60
            n = int(x[f:colon])
 
61
        except (OverflowError, ValueError):
 
62
            n = long(x[f:colon])
 
63
        if x[f] == '0' and colon != f+1:
 
64
            raise ValueError
 
65
        colon += 1
 
66
        return (x[colon:colon+n], colon+n)
 
67
 
 
68
    def decode_list(self, x, f):
 
69
        r, f = [], f+1
 
70
        while x[f] != 'e':
 
71
            v, f = self.decode_func[x[f]](x, f)
 
72
            r.append(v)
 
73
        if self.yield_tuples:
 
74
            r = tuple(r)
 
75
        return (r, f + 1)
 
76
 
 
77
    def decode_dict(self, x, f):
 
78
        r, f = {}, f+1
 
79
        lastkey = None
 
80
        while x[f] != 'e':
 
81
            k, f = self.decode_string(x, f)
 
82
            if lastkey >= k:
 
83
                raise ValueError
 
84
            lastkey = k
 
85
            r[k], f = self.decode_func[x[f]](x, f)
 
86
        return (r, f + 1)
 
87
 
 
88
    def bdecode(self, x):
 
89
        try:
 
90
            r, l = self.decode_func[x[0]](x, 0)
 
91
        except (IndexError, KeyError):
 
92
            raise ValueError
 
93
        if l != len(x):
 
94
            raise ValueError
 
95
        return r
 
96
 
 
97
 
 
98
_decoder = BDecoder()
 
99
bdecode = _decoder.bdecode
 
100
 
 
101
_tuple_decoder = BDecoder(True)
 
102
bdecode_as_tuple = _tuple_decoder.bdecode
 
103
 
 
104
 
 
105
from types import StringType, IntType, LongType, DictType, ListType, TupleType
 
106
 
 
107
class Bencached(object):
 
108
    __slots__ = ['bencoded']
 
109
 
 
110
    def __init__(self, s):
 
111
        self.bencoded = s
 
112
 
 
113
def encode_bencached(x,r):
 
114
    r.append(x.bencoded)
 
115
 
 
116
def encode_int(x, r):
 
117
    r.extend(('i', str(x), 'e'))
 
118
 
 
119
def encode_string(x, r):
 
120
    r.extend((str(len(x)), ':', x))
 
121
 
 
122
def encode_list(x, r):
 
123
    r.append('l')
 
124
    for i in x:
 
125
        encode_func[type(i)](i, r)
 
126
    r.append('e')
 
127
 
 
128
def encode_dict(x,r):
 
129
    r.append('d')
 
130
    ilist = x.items()
 
131
    ilist.sort()
 
132
    for k, v in ilist:
 
133
        r.extend((str(len(k)), ':', k))
 
134
        encode_func[type(v)](v, r)
 
135
    r.append('e')
 
136
 
 
137
encode_func = {}
 
138
encode_func[type(Bencached(0))] = encode_bencached
 
139
encode_func[IntType] = encode_int
 
140
encode_func[LongType] = encode_int
 
141
encode_func[StringType] = encode_string
 
142
encode_func[ListType] = encode_list
 
143
encode_func[TupleType] = encode_list
 
144
encode_func[DictType] = encode_dict
 
145
 
 
146
try:
 
147
    from types import BooleanType
 
148
except ImportError:
 
149
    pass
 
150
else:
 
151
    def encode_bool(x,r):
 
152
        encode_int(int(x), r)
 
153
    encode_func[BooleanType] = encode_bool
 
154
 
 
155
 
 
156
def bencode(x):
 
157
    r = []
 
158
    encode_func[type(x)](x, r)
 
159
    return ''.join(r)
 
160