~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_parse_btree_c.pyx

  • Committer: John Arbash Meinel
  • Date: 2008-08-21 22:28:39 UTC
  • mto: This revision was merged to the branch mainline in revision 3644.
  • Revision ID: john@arbash-meinel.com-20080821222839-xy2yufgx6m6zzzt2
Shave off some more time by using exact accessors.
Basically, the inner access is using PyTuple and PyString functions
instead of their PyObject counterparts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
    ctypedef unsigned size_t
21
21
 
22
22
cdef extern from "Python.h":
 
23
    ctypedef struct PyObject:
 
24
        pass
23
25
    int PyList_Append(object lst, object item) except -1
24
26
 
25
 
    char *PyString_AsString(object p)
 
27
    char *PyString_AsString(object p) except NULL
26
28
    object PyString_FromStringAndSize(char *, Py_ssize_t)
27
29
    int PyString_CheckExact(object s)
 
30
    int PyString_CheckExact_ptr "PyString_CheckExact" (PyObject *)
28
31
    Py_ssize_t PyString_Size(object p)
 
32
    Py_ssize_t PyString_GET_SIZE_ptr "PyString_GET_SIZE" (PyObject *)
 
33
    char * PyString_AS_STRING_ptr "PyString_AS_STRING" (PyObject *)
 
34
    int PyString_AsStringAndSize_ptr(PyObject *, char **buf, Py_ssize_t *len)
29
35
    int PyTuple_CheckExact(object t)
 
36
    Py_ssize_t PyTuple_GET_SIZE(object t)
 
37
    PyObject *PyTuple_GET_ITEM_ptr_object "PyTuple_GET_ITEM" (object tpl, int index)
30
38
 
31
39
cdef extern from "string.h":
32
40
    void *memcpy(void *dest, void *src, size_t n)
125
133
                                                   last - self._start)))
126
134
                    raise AssertionError(failure_string)
127
135
            # capture the key string
 
136
            # TODO: Consider using PyIntern_FromString, the only caveat is that
 
137
            # it assumes a NULL-terminated string, so we have to check if
 
138
            # temp_ptr[0] == c'\0' or some other char.
128
139
            key_element = safe_string_from_size(self._start,
129
140
                                                temp_ptr - self._start)
130
141
            # advance our pointer
257
268
    """
258
269
    cdef Py_ssize_t flat_len
259
270
    cdef Py_ssize_t key_len
 
271
    cdef Py_ssize_t node_len
 
272
    cdef PyObject * val
260
273
    cdef char * value
261
274
    cdef Py_ssize_t value_len
262
275
    cdef char * out
263
 
    cdef Py_ssize_t ref_len
 
276
    cdef Py_ssize_t refs_len
264
277
    cdef Py_ssize_t next_len
265
278
    cdef int first_ref_list
266
279
    cdef int first_reference
267
 
    cdef int first_bit
 
280
    cdef int i
 
281
    cdef PyObject *ref_bit
 
282
    cdef Py_ssize_t ref_bit_len
268
283
 
 
284
    if not PyTuple_CheckExact(node):
 
285
        raise TypeError('We expected a tuple() for node not: %s'
 
286
            % type(node))
 
287
    node_len = PyTuple_GET_SIZE(node)
 
288
    if reference_lists:
 
289
        if node_len != 4:
 
290
            raise ValueError('With ref_lists, we expected 4 entries not: %s'
 
291
                % len(node))
 
292
    elif node_len < 3:
 
293
        raise ValueError('Without ref_lists, we need at least 3 entries not: %s'
 
294
            % len(node))
269
295
    # I don't expect that we can do faster than string.join()
270
 
    string_key = '\0'.join(node[1])
 
296
    string_key = '\0'.join(<object>PyTuple_GET_ITEM_ptr_object(node, 1))
271
297
 
272
298
    # TODO: instead of using string joins, precompute the final string length,
273
299
    #       and then malloc a single string and copy everything in.
281
307
    # ref_list := ref (CR ref)*
282
308
    # ref := BYTES (NULL BYTES)*
283
309
    # value := BYTES
284
 
    ref_len = 0
 
310
    refs_len = 0
285
311
    if reference_lists:
286
312
        # Figure out how many bytes it will take to store the references
287
313
        ref_lists = node[3]
290
316
            # If there are no nodes, we don't need to do any work
291
317
            # Otherwise we will need (len - 1) '\t' characters to separate
292
318
            # the reference lists
293
 
            ref_len = ref_len + (next_len - 1)
 
319
            refs_len = refs_len + (next_len - 1)
294
320
            for ref_list in ref_lists:
295
321
                next_len = len(ref_list)
296
322
                if next_len > 0:
297
323
                    # We will need (len - 1) '\r' characters to separate the
298
324
                    # references
299
 
                    ref_len = ref_len + (next_len - 1)
 
325
                    refs_len = refs_len + (next_len - 1)
300
326
                    for reference in ref_list:
301
 
                        next_len = len(reference)
 
327
                        if not PyTuple_CheckExact(reference):
 
328
                            raise TypeError(
 
329
                                'We expect references to be tuples not: %s'
 
330
                                % type(reference))
 
331
                        next_len = PyTuple_GET_SIZE(reference)
302
332
                        if next_len > 0:
303
333
                            # We will need (len - 1) '\x00' characters to
304
334
                            # separate the reference key
305
 
                            ref_len = ref_len + (next_len - 1)
306
 
                            for ref in reference:
307
 
                                ref_len = ref_len + PyString_Size(ref)
 
335
                            refs_len = refs_len + (next_len - 1)
 
336
                            for i from 0 <= i < next_len:
 
337
                                ref_bit = PyTuple_GET_ITEM_ptr_object(reference, i)
 
338
                                if not PyString_CheckExact(<object>ref_bit):
 
339
                                    raise TypeError('We expect reference bits'
 
340
                                        ' to be strings not: %s'
 
341
                                        % type(<object>ref_bit))
 
342
                                refs_len = refs_len + PyString_GET_SIZE_ptr(ref_bit)
308
343
 
309
344
    # So we have the (key NULL refs NULL value LF)
310
345
    key_len = PyString_Size(string_key)
311
 
    value = PyString_AsString(node[2])
312
 
    value_len = PyString_Size(node[2])
313
 
    flat_len = (key_len + 1 + ref_len + 1 + value_len + 1)
 
346
    val = PyTuple_GET_ITEM_ptr_object(node, 2)
 
347
    if not PyString_CheckExact(<object>val):
 
348
        raise TypeError('Expected a plain str for value not: %s'
 
349
                        % type(<object>val))
 
350
    value = PyString_AS_STRING_ptr(val)
 
351
    value_len = PyString_GET_SIZE_ptr(val)
 
352
    flat_len = (key_len + 1 + refs_len + 1 + value_len + 1)
314
353
    line = PyString_FromStringAndSize(NULL, flat_len)
315
354
    # Get a pointer to the new buffer
316
355
    out = PyString_AsString(line)
318
357
    out = out + key_len
319
358
    out[0] = c'\0'
320
359
    out = out + 1
321
 
    if ref_len > 0:
 
360
    if refs_len > 0:
322
361
        first_ref_list = 1
323
362
        for ref_list in ref_lists:
324
363
            if first_ref_list == 0:
331
370
                    out[0] = c'\r'
332
371
                    out = out + 1
333
372
                first_reference = 0
334
 
                first_bit = 1
335
 
                for bit in reference:
336
 
                    if first_bit == 0:
 
373
                next_len = PyTuple_GET_SIZE(reference)
 
374
                for i from 0 <= i < next_len:
 
375
                    if i != 0:
337
376
                        out[0] = c'\x00'
338
377
                        out = out + 1
339
 
                    first_bit = 0
340
 
                    next_len = PyString_Size(bit)
341
 
                    memcpy(out, PyString_AsString(bit), next_len)
342
 
                    out = out + next_len
 
378
                    ref_bit = PyTuple_GET_ITEM_ptr_object(reference, i)
 
379
                    ref_bit_len = PyString_GET_SIZE_ptr(ref_bit)
 
380
                    memcpy(out, PyString_AS_STRING_ptr(ref_bit), ref_bit_len)
 
381
                    out = out + ref_bit_len
343
382
    out[0] = c'\0'
344
383
    out = out  + 1
345
384
    memcpy(out, value, value_len)