~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_bencode_pyx.pyx

  • Committer: John Arbash Meinel
  • Date: 2009-06-04 15:54:21 UTC
  • mto: This revision was merged to the branch mainline in revision 4410.
  • Revision ID: john@arbash-meinel.com-20090604155421-wdxp4le2q49jvg2q
Move self._update_tail into a macro for UPDATE_TAIL.

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
cdef extern from "python-compat.h":
50
50
    int snprintf(char* buffer, size_t nsize, char* fmt, ...)
51
51
 
52
 
 
53
 
cdef class Decoder:
 
52
cdef class Coder:
 
53
    """Base class for both Decoder and Encoder"""
 
54
 
 
55
    cdef readonly char *tail
 
56
    cdef readonly int size
 
57
 
 
58
cdef extern from "_bencode_pyx.h":
 
59
    void UPDATE_TAIL(Coder, int n)
 
60
    int MAX_INT_AS_STR
 
61
 
 
62
 
 
63
 
 
64
cdef class Decoder(Coder):
54
65
    """Bencode decoder"""
55
66
 
56
 
    cdef readonly char *tail
57
 
    cdef readonly int size
58
67
    cdef readonly int _yield_tuples
59
68
    cdef object text
60
69
 
87
96
        try:
88
97
            ch = self.tail[0]
89
98
            if ch == c'i':
90
 
                self._update_tail(1)
 
99
                UPDATE_TAIL(self, 1)
91
100
                return self._decode_int()
92
101
            elif c'0' <= ch <= c'9':
93
102
                return self._decode_string()
94
103
            elif ch == c'l':
95
 
                self._update_tail(1)
 
104
                UPDATE_TAIL(self, 1)
96
105
                return self._decode_list()
97
106
            elif ch == c'd':
98
 
                self._update_tail(1)
 
107
                UPDATE_TAIL(self, 1)
99
108
                return self._decode_dict()
100
109
            else:
101
110
                raise ValueError('unknown object type identifier %r' % ch)
105
114
    cdef void _update_tail(self, int n):
106
115
        """Update tail pointer and resulting size by n characters"""
107
116
        self.size = self.size - n
108
 
        self.tail = &self.tail[n]
 
117
        self.tail = self.tail + n
109
118
 
110
119
    cdef int _read_digits(self, char stop_char) except -1:
111
120
        cdef int i
133
142
            ret = PyInt_FromString(self.tail, NULL, 10)
134
143
        finally:
135
144
            self.tail[i] = c'e'
136
 
        self._update_tail(i+1)
 
145
        UPDATE_TAIL(self, i+1)
137
146
        return ret
138
147
 
139
148
    cdef object _decode_string(self):
140
149
        cdef int n, i
141
150
        i = self._read_digits(c':')
142
151
        n = strtol(self.tail, NULL, 10)
143
 
        self._update_tail(i+1)
 
152
        UPDATE_TAIL(self, i+1)
144
153
        if n == 0:
145
154
            return ''
146
155
        if n > self.size:
149
158
            raise ValueError('string size below zero: %d' % n)
150
159
 
151
160
        result = PyString_FromStringAndSize(self.tail, n)
152
 
        self._update_tail(n)
 
161
        UPDATE_TAIL(self, n)
153
162
        return result
154
163
 
155
164
    cdef object _decode_list(self):
157
166
 
158
167
        while self.size > 0:
159
168
            if self.tail[0] == c'e':
160
 
                self._update_tail(1)
 
169
                UPDATE_TAIL(self, 1)
161
170
                if self._yield_tuples:
162
171
                    return tuple(result)
163
172
                else:
176
185
        while self.size > 0:
177
186
            ch = self.tail[0]
178
187
            if ch == c'e':
179
 
                self._update_tail(1)
 
188
                UPDATE_TAIL(self, 1)
180
189
                return result
181
190
            else:
182
191
                # keys should be strings only
213
222
    INT_BUF_SIZE = 32
214
223
 
215
224
 
216
 
cdef class Encoder:
 
225
cdef class Encoder(Coder):
217
226
    """Bencode encoder"""
218
227
 
219
228
    cdef readonly char *buffer
220
229
    cdef readonly int maxsize
221
 
    cdef readonly char *tail
222
 
    cdef readonly int size
223
230
 
224
231
    def __init__(self, int maxsize=INITSIZE):
225
232
        """Initialize encoder engine
287
294
        n = snprintf(self.tail, INT_BUF_SIZE, "i%de", x)
288
295
        if n < 0:
289
296
            raise MemoryError('int %d too big to encode' % x)
290
 
        self._update_tail(n)
 
297
        UPDATE_TAIL(self, n)
291
298
        return 1
292
299
 
293
300
    cdef int _encode_long(self, x) except 0:
296
303
    cdef int _append_string(self, s) except 0:
297
304
        self._ensure_buffer(PyString_GET_SIZE(s))
298
305
        memcpy(self.tail, PyString_AS_STRING(s), PyString_GET_SIZE(s))
299
 
        self._update_tail(PyString_GET_SIZE(s))
 
306
        UPDATE_TAIL(self, PyString_GET_SIZE(s))
300
307
        return 1
301
308
 
302
309
    cdef int _encode_string(self, x) except 0:
303
310
        cdef int n
304
 
        self._ensure_buffer(PyString_GET_SIZE(x) + 32)
305
 
        n = snprintf(self.tail, 32, '%d:', PyString_GET_SIZE(x))
 
311
        self._ensure_buffer(PyString_GET_SIZE(x) + INT_BUF_SIZE)
 
312
        n = snprintf(self.tail, INT_BUF_SIZE, '%d:', PyString_GET_SIZE(x))
306
313
        if n < 0:
307
314
            raise MemoryError('string %s too big to encode' % x)
308
315
        memcpy(<void *>(self.tail+n), PyString_AS_STRING(x),
309
316
               PyString_GET_SIZE(x))
310
 
        self._update_tail(n+PyString_GET_SIZE(x))
 
317
        UPDATE_TAIL(self, n+PyString_GET_SIZE(x))
311
318
        return 1
312
319
 
313
320
    cdef int _encode_list(self, x) except 0:
314
321
        self._ensure_buffer(2)
315
322
        self.tail[0] = c'l'
316
 
        self._update_tail(1)
 
323
        UPDATE_TAIL(self, 1)
317
324
 
318
325
        for i in x:
319
326
            self.process(i)
320
327
 
321
328
        self.tail[0] = c'e'
322
 
        self._update_tail(1)
 
329
        UPDATE_TAIL(self, 1)
323
330
        return 1
324
331
 
325
332
    cdef int _encode_dict(self, x) except 0:
326
333
        self._ensure_buffer(2)
327
334
        self.tail[0] = c'd'
328
 
        self._update_tail(1)
 
335
        UPDATE_TAIL(self, 1)
329
336
 
330
337
        keys = x.keys()
331
338
        keys.sort()
336
343
            self.process(x[k])
337
344
 
338
345
        self.tail[0] = c'e'
339
 
        self._update_tail(1)
 
346
        UPDATE_TAIL(self, 1)
340
347
        return 1
341
348
 
342
349
    def process(self, object x):