~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_bencode_c.pyx

  • Committer: Jelmer Vernooij
  • Date: 2009-05-28 01:28:44 UTC
  • mto: (4398.5.1 bencode_serializer)
  • mto: This revision was merged to the branch mainline in revision 4410.
  • Revision ID: jelmer@samba.org-20090528012844-ico452ygxwwcvr4z
add handling of deep nesting.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
"""Pyrex implementation for bencode coder/decoder"""
18
18
 
19
19
 
 
20
cdef extern from "stddef.h":
 
21
    ctypedef unsigned int size_t
 
22
 
20
23
cdef extern from "Python.h":
21
24
    ctypedef int  Py_ssize_t
22
25
    int PyInt_CheckExact(object o)
30
33
    char *PyString_AS_STRING(object o) except NULL
31
34
    Py_ssize_t PyString_GET_SIZE(object o) except -1
32
35
    object PyInt_FromString(char *str, char **pend, int base)
33
 
 
34
 
cdef extern from "stddef.h":
35
 
    ctypedef unsigned int size_t
 
36
    int Py_GetRecursionLimit()
 
37
    int Py_EnterRecursiveCall(char *)
 
38
    void Py_LeaveRecursiveCall()
36
39
 
37
40
cdef extern from "stdlib.h":
38
41
    void free(void *memblock)
51
54
    """Bencode decoder"""
52
55
 
53
56
    cdef readonly char *tail
54
 
    cdef readonly int   size
 
57
    cdef readonly int size
55
58
 
56
 
    cdef readonly int    _yield_tuples
 
59
    cdef readonly int _yield_tuples
57
60
 
58
61
    def __init__(self, s, yield_tuples=0):
59
62
        """Initialize decoder engine.
78
81
        if 0 == self.size:
79
82
            raise ValueError('stream underflow')
80
83
 
81
 
        ch = self.tail[0]
82
 
 
83
 
        if ch == c'i':
84
 
            self._update_tail(1)
85
 
            return self._decode_int()
86
 
        elif c'0' <= ch <= c'9':
87
 
            return self._decode_string()
88
 
        elif ch == c'l':
89
 
            self._update_tail(1)
90
 
            return self._decode_list()
91
 
        elif ch == c'd':
92
 
            self._update_tail(1)
93
 
            return self._decode_dict()
94
 
        else:
95
 
            raise ValueError('unknown object type identifier %r' % ch)
 
84
        if Py_EnterRecursiveCall("decode_object"):
 
85
            raise RuntimeError("too deeply nested")
 
86
        try:
 
87
            ch = self.tail[0]
 
88
            if ch == c'i':
 
89
                self._update_tail(1)
 
90
                return self._decode_int()
 
91
            elif c'0' <= ch <= c'9':
 
92
                return self._decode_string()
 
93
            elif ch == c'l':
 
94
                self._update_tail(1)
 
95
                return self._decode_list()
 
96
            elif ch == c'd':
 
97
                self._update_tail(1)
 
98
                return self._decode_dict()
 
99
            else:
 
100
                raise ValueError('unknown object type identifier %r' % ch)
 
101
        finally:
 
102
            Py_LeaveRecursiveCall()
96
103
 
97
104
    cdef void _update_tail(self, int n):
98
105
        """Update tail pointer and resulting size by n characters"""
206
213
    """Bencode encoder"""
207
214
 
208
215
    cdef readonly char *buffer
209
 
    cdef readonly int   maxsize
 
216
    cdef readonly int maxsize
210
217
    cdef readonly char *tail
211
 
    cdef readonly int   size
 
218
    cdef readonly int size
212
219
 
213
220
    def __init__(self, int maxsize=INITSIZE):
214
221
        """Initialize encoder engine
329
336
        return 1
330
337
 
331
338
    def process(self, object x):
332
 
        if PyString_CheckExact(x):
333
 
            self._encode_string(x)
334
 
        elif PyInt_CheckExact(x):
335
 
            self._encode_int(x)
336
 
        elif PyLong_CheckExact(x):
337
 
            self._encode_long(x)
338
 
        elif PyList_CheckExact(x) or PyTuple_CheckExact(x):
339
 
            self._encode_list(x)
340
 
        elif PyDict_CheckExact(x):
341
 
            self._encode_dict(x)
342
 
        elif PyBool_Check(x):
343
 
            self._encode_int(int(x))
344
 
        elif isinstance(x, Bencached):
345
 
            self._append_string(x.bencoded)
346
 
        else:
347
 
            raise TypeError('unsupported type %r' % x)
 
339
        if Py_EnterRecursiveCall("encode"):
 
340
            raise RuntimeError("too deeply nested")
 
341
        try:
 
342
            if PyString_CheckExact(x):
 
343
                self._encode_string(x)
 
344
            elif PyInt_CheckExact(x):
 
345
                self._encode_int(x)
 
346
            elif PyLong_CheckExact(x):
 
347
                self._encode_long(x)
 
348
            elif PyList_CheckExact(x) or PyTuple_CheckExact(x):
 
349
                self._encode_list(x)
 
350
            elif PyDict_CheckExact(x):
 
351
                self._encode_dict(x)
 
352
            elif PyBool_Check(x):
 
353
                self._encode_int(int(x))
 
354
            elif isinstance(x, Bencached):
 
355
                self._append_string(x.bencoded)
 
356
            else:
 
357
                raise TypeError('unsupported type %r' % x)
 
358
        finally:
 
359
            Py_LeaveRecursiveCall()
348
360
 
349
361
 
350
362
def bencode(x):