~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-27 13:53:53 UTC
  • mto: (4398.5.1 bencode_serializer)
  • mto: This revision was merged to the branch mainline in revision 4410.
  • Revision ID: jelmer@samba.org-20090527135353-sp015519lnj29zj2
Simplify the code a bit more.

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
    object PyString_FromStringAndSize(char *v, Py_ssize_t len)
30
30
    char *PyString_AS_STRING(object o) except NULL
31
31
    Py_ssize_t PyString_GET_SIZE(object o) except -1
32
 
    long PyInt_GetMax()
33
32
    object PyLong_FromString(char *str, char **pend, int base)
34
33
 
35
34
cdef extern from "stddef.h":
39
38
    void free(void *memblock)
40
39
    void *malloc(size_t size)
41
40
    void *realloc(void *memblock, size_t size)
 
41
    long strtol(char *, char **, int)
42
42
 
43
43
cdef extern from "string.h":
44
44
    void *memcpy(void *dest, void *src, size_t count)
 
45
    char *strndup(char *src, size_t count)
45
46
 
46
47
cdef extern from "python-compat.h":
47
48
    int snprintf(char* buffer, size_t nsize, char* fmt, ...)
53
54
    cdef readonly char *tail
54
55
    cdef readonly int   size
55
56
 
56
 
    cdef readonly long   _MAXINT
57
 
    cdef readonly int    _MAXN
58
 
    cdef readonly object _longint
59
57
    cdef readonly int    _yield_tuples
60
58
 
61
59
    def __init__(self, s, yield_tuples=0):
69
67
        self.size = PyString_GET_SIZE(s)
70
68
        self._yield_tuples = int(yield_tuples)
71
69
 
72
 
        self._MAXINT = PyInt_GetMax()
73
 
        self._MAXN = len(str(self._MAXINT))
74
 
        self._longint = long(0)
75
 
 
76
70
    def decode(self):
77
71
        result = self.decode_object()
78
72
        if self.size != 0:
106
100
        self.size = self.size - n
107
101
        self.tail = &self.tail[n]
108
102
 
 
103
    cdef char *_read_digits(self, char stop_char) except NULL:
 
104
        cdef char *ret
 
105
        i = 0
 
106
        while ((self.tail[i] >= c'0' and self.tail[i] <= c'9') or 
 
107
               self.tail[i] == c'-') and i < self.size:
 
108
            i += 1
 
109
 
 
110
        if self.tail[i] != stop_char:
 
111
            raise ValueError("Stop character %c not found: %c" % 
 
112
                (stop_char, self.tail[i]))
 
113
        if (self.tail[0] == c'0' or 
 
114
                (self.tail[0] == c'-' and self.tail[1] == c'0')):
 
115
            if i == 1:
 
116
                self._update_tail(i+1)
 
117
                return strndup("0", 1)
 
118
            else:
 
119
                raise ValueError # leading zeroes are not allowed
 
120
        ret = <char*>strndup(self.tail, i)
 
121
        if NULL == ret:
 
122
            raise MemoryError 
 
123
        self._update_tail(i+1)
 
124
        return ret
 
125
 
109
126
    cdef object _decode_int(self):
110
 
        cdef int result
111
 
        result = self._decode_int_until(c'e')
112
 
        if result != self._MAXINT:
113
 
            return result
114
 
        else:
115
 
            return self._longint
116
 
 
117
 
    cdef int _decode_int_until(self, char stop_char) except? -1:
118
 
        """Decode int from stream until stop_char encountered"""
119
 
        cdef int result
120
 
        cdef int i, n
121
 
        cdef int sign
122
 
        cdef char digit
123
 
        cdef char *longstr
124
 
 
125
 
        for n from 0 <= n < self.size:
126
 
            if self.tail[n] == stop_char:
127
 
                break
128
 
        else:
129
 
            raise ValueError
130
 
 
131
 
        sign = 0
132
 
        if c'-' == self.tail[0]:
133
 
            sign = 1
134
 
 
135
 
        if n-sign == 0:
136
 
            raise ValueError    # ie / i-e
137
 
 
138
 
        if self.tail[sign] == c'0':   # special check for zero
139
 
            if sign:
140
 
                raise ValueError    # i-0e
141
 
            if n > 1:
142
 
                raise ValueError    # i00e / i01e
143
 
            self._update_tail(n+1)
144
 
            return 0
145
 
 
146
 
        if n-sign < self._MAXN:
147
 
            # plain int
148
 
            result = 0
149
 
            for i from sign <= i < n:
150
 
                digit = self.tail[i]
151
 
                if c'0' <= digit <= c'9':
152
 
                    result = result * 10 + (digit - c'0')
153
 
                else:
154
 
                    raise ValueError
155
 
            if sign:
156
 
                result = -result
157
 
            self._update_tail(n+1)
158
 
        else:
159
 
            # long int
160
 
            result = self._MAXINT
161
 
            longstr = <char*>malloc(n+1)
162
 
            if NULL == longstr:
163
 
                raise MemoryError 
164
 
            memcpy(longstr, self.tail, n)
165
 
            longstr[n] = 0
166
 
            self._longint = PyLong_FromString(longstr, NULL, 10)
167
 
            free(longstr)
168
 
            self._update_tail(n+1)
169
 
 
 
127
        cdef char *longstr, *tail
 
128
        longstr = self._read_digits(c'e')
 
129
        result = PyLong_FromString(longstr, &tail, 10)
 
130
        free(longstr)
170
131
        return result
171
132
 
172
133
    cdef object _decode_string(self):
 
134
        cdef char *longstr, *tail
173
135
        cdef int n
174
 
 
175
 
        n = self._decode_int_until(c':')
 
136
        longstr = self._read_digits(c':')
 
137
        # long int
 
138
        n = strtol(longstr, &tail, 10)
 
139
        if tail[0] != c'\0':
 
140
            raise ValueError("Tail invalid: %s" % longstr)
 
141
        free(longstr)
176
142
        if n == 0:
177
143
            return ''
178
 
        if n == self._MAXINT:
179
 
            # strings longer than 1GB is not supported
180
 
            raise ValueError('too long string')
181
144
        if n > self.size:
182
145
            raise ValueError('stream underflow')
183
146
        if n < 0: