~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_chk_map_pyx.pyx

  • Committer: John Arbash Meinel
  • Date: 2010-05-11 10:45:26 UTC
  • mto: This revision was merged to the branch mainline in revision 5225.
  • Revision ID: john@arbash-meinel.com-20100511104526-zxnstcxta22hzw2n
Implement a compiled extension for parsing the text key out of a CHKInventory value.

Related to bug #562666. This seems to shave 5-10% out of the time spent doing a complete
branch of bzr.dev/launchpad/etc.

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
    Py_ssize_t PyTuple_GET_SIZE(object t)
36
36
    int PyString_CheckExact(object)
37
37
    char *PyString_AS_STRING(object s)
 
38
    PyObject *PyString_FromStringAndSize_ptr "PyString_FromStringAndSize" (char *, Py_ssize_t)
38
39
    Py_ssize_t PyString_GET_SIZE(object)
 
40
    void PyString_InternInPlace(PyObject **)
39
41
    unsigned long PyInt_AsUnsignedLongMask(object) except? -1
40
42
 
41
43
    int PyDict_SetItem(object d, object k, object v) except -1
44
46
    void PyTuple_SET_ITEM(object t, Py_ssize_t offset, object)
45
47
 
46
48
    void Py_INCREF(object)
 
49
    void Py_DECREF_ptr "Py_DECREF" (PyObject *)
47
50
 
48
51
    PyObject * PyTuple_GET_ITEM_ptr "PyTuple_GET_ITEM" (object t,
49
52
                                                        Py_ssize_t offset)
93
96
    return NULL
94
97
 
95
98
 
 
99
cdef object safe_interned_string_from_size(char *s, Py_ssize_t size):
 
100
    cdef PyObject *py_str
 
101
    if size < 0:
 
102
        raise AssertionError(
 
103
            'tried to create a string with an invalid size: %d @0x%x'
 
104
            % (size, <int>s))
 
105
    py_str = PyString_FromStringAndSize_ptr(s, size)
 
106
    PyString_InternInPlace(&py_str)
 
107
    result = <object>py_str
 
108
    # Casting a PyObject* to an <object> triggers an INCREF from Pyrex, so we
 
109
    # DECREF it to avoid geting immortal strings
 
110
    Py_DECREF_ptr(py_str)
 
111
    return result
 
112
 
 
113
 
96
114
def _search_key_16(key):
97
115
    """See chk_map._search_key_16."""
98
116
    cdef Py_ssize_t num_bits
395
413
    result._node_width = len(item_prefix)
396
414
    result._search_prefix = PyString_FromStringAndSize(prefix, prefix_length)
397
415
    return result
 
416
 
 
417
 
 
418
def _bytes_to_text_key(bytes):
 
419
    """Take a CHKInventory value string and return a (file_id, rev_id) tuple"""
 
420
    cdef StaticTuple key
 
421
    cdef char *byte_str, *cur_end, *file_id_str, *byte_end
 
422
    cdef char *revision_str
 
423
    cdef Py_ssize_t byte_size, pos, file_id_len
 
424
 
 
425
    if not PyString_CheckExact(bytes):
 
426
        raise TypeError('bytes must be a string')
 
427
    byte_str = PyString_AS_STRING(bytes)
 
428
    byte_size = PyString_GET_SIZE(bytes)
 
429
    byte_end = byte_str + byte_size
 
430
    cur_end = <char*>memchr(byte_str, c':', byte_size)
 
431
    if cur_end == NULL:
 
432
        raise ValueError('No kind section found.')
 
433
    if cur_end[1] != ' ':
 
434
        raise ValueError('Kind section should end with ": "')
 
435
    file_id_str = cur_end + 2
 
436
    # file_id is now the data up until the next newline
 
437
    cur_end = <char*>memchr(file_id_str, c'\n', byte_end - file_id_str)
 
438
    if cur_end == NULL:
 
439
        raise ValueError('no newline after file-id')
 
440
    file_id = safe_interned_string_from_size(file_id_str,
 
441
                                             cur_end - file_id_str)
 
442
    # this is the end of the parent_str
 
443
    cur_end = <char*>memchr(cur_end + 1, c'\n', byte_end - cur_end - 1)
 
444
    if cur_end == NULL:
 
445
        raise ValueError('no newline after parent_str')
 
446
    # end of the name str
 
447
    cur_end = <char*>memchr(cur_end + 1, c'\n', byte_end - cur_end - 1)
 
448
    if cur_end == NULL:
 
449
        raise ValueError('no newline after name str')
 
450
    # the next section is the revision info
 
451
    revision_str = cur_end + 1
 
452
    cur_end = <char*>memchr(cur_end + 1, c'\n', byte_end - cur_end - 1)
 
453
    if cur_end == NULL:
 
454
        # This is probably a dir: entry, which has revision as the last item
 
455
        cur_end = byte_end
 
456
    revision = safe_interned_string_from_size(revision_str,
 
457
        cur_end - revision_str)
 
458
    key = StaticTuple_New(2)
 
459
    Py_INCREF(file_id)
 
460
    StaticTuple_SET_ITEM(key, 0, file_id) 
 
461
    Py_INCREF(revision)
 
462
    StaticTuple_SET_ITEM(key, 1, revision) 
 
463
    return StaticTuple_Intern(key)