~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 10:47:31 UTC
  • mto: (4398.5.1 bencode_serializer)
  • mto: This revision was merged to the branch mainline in revision 4410.
  • Revision ID: jelmer@samba.org-20090527104731-q9foq6da41ip9x7y
Simplify dict parsing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
16
 
18
17
"""Pyrex implementation for bencode coder/decoder"""
19
18
 
31
30
    char *PyString_AS_STRING(object o) except NULL
32
31
    Py_ssize_t PyString_GET_SIZE(object o) except -1
33
32
    long PyInt_GetMax()
34
 
    object PyLong_FromLong(unsigned long)
 
33
    object PyLong_FromString(char *str, char **pend, int base)
35
34
 
36
35
cdef extern from "stddef.h":
37
36
    ctypedef unsigned int size_t
40
39
    void free(void *memblock)
41
40
    void *malloc(size_t size)
42
41
    void *realloc(void *memblock, size_t size)
43
 
    long int strtol(char *nptr, char **endptr, int base)
44
 
 
45
42
 
46
43
cdef extern from "string.h":
47
44
    void *memcpy(void *dest, void *src, size_t count)
48
 
    char *memchr(void *dest, int size, char c)
49
45
 
50
46
cdef extern from "python-compat.h":
51
47
    int snprintf(char* buffer, size_t nsize, char* fmt, ...)
120
116
 
121
117
    cdef int _decode_int_until(self, char stop_char) except? -1:
122
118
        """Decode int from stream until stop_char encountered"""
123
 
        cdef char *actual_tail, *expected_tail
124
 
        cdef int n
125
 
        expected_tail = memchr(self.tail, self.size, stop_char)
126
 
        if expected_tail == NULL:
127
 
            raise ValueError
128
 
        ret = PyLong_FromLong(strtol(self.tail, &actual_tail, 10))
129
 
        if actual_tail != expected_tail or actual_tail == self.tail:
130
 
            raise ValueError
131
 
        self._update_tail(actual_tail - self.tail)
132
 
        return ret
 
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
 
 
170
        return result
133
171
 
134
172
    cdef object _decode_string(self):
135
173
        cdef int n
175
213
            if ch == c'e':
176
214
                self._update_tail(1)
177
215
                return result
178
 
            elif c'0' <= ch <= c'9':
 
216
            else:
179
217
                # keys should be strings only
180
218
                key = self._decode_string()
181
219
                if lastkey >= key:
184
222
                    lastkey = key
185
223
                value = self.decode_object()
186
224
                result[key] = value
187
 
            else:
188
 
                raise ValueError('keys in dict should be strings only')
189
225
 
190
226
        raise ValueError('malformed dict')
191
227