/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/_chk_map_pyx.pyx

  • Committer: Marius Kruger
  • Date: 2010-07-10 21:28:56 UTC
  • mto: (5384.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 5385.
  • Revision ID: marius.kruger@enerweb.co.za-20100710212856-uq4ji3go0u5se7hx
* Update documentation
* add NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
from __future__ import absolute_import
18
17
 
 
18
#python2.4 support
19
19
cdef extern from "python-compat.h":
20
20
    pass
21
21
 
22
 
from libc.stdio cimport (
23
 
    sprintf,
24
 
    )
25
 
from libc.stdlib cimport (
26
 
    strtol,
27
 
    )
28
 
from libc.string cimport (
29
 
    memcmp,
30
 
    memcpy,
31
 
    memchr,
32
 
    )
33
 
 
34
 
from cpython.bytes cimport (
35
 
    PyBytes_CheckExact,
36
 
    PyBytes_FromStringAndSize,
37
 
    PyBytes_AS_STRING,
38
 
    PyBytes_GET_SIZE,
39
 
    )
40
 
from cpython.dict cimport (
41
 
    PyDict_SetItem,
42
 
    )
43
 
from cpython.int cimport (
44
 
    PyInt_AsUnsignedLongMask,
45
 
    )
46
 
from cpython.object cimport (
47
 
    PyObject,
48
 
    )
49
 
from cpython.ref cimport (
50
 
    Py_INCREF,
51
 
    )
52
 
from cpython.tuple cimport (
53
 
    PyTuple_CheckExact,
54
 
    PyTuple_GET_SIZE,
55
 
    )
56
 
 
57
 
from ._str_helpers cimport (
58
 
    _my_memrchr,
59
 
    safe_interned_string_from_size,
60
 
    )
 
22
cdef extern from *:
 
23
    ctypedef unsigned int size_t
 
24
    int memcmp(void *, void*, size_t)
 
25
    void memcpy(void *, void*, size_t)
 
26
    void *memchr(void *s, int c, size_t len)
 
27
    long strtol(char *, char **, int)
 
28
    void sprintf(char *, char *, ...)
 
29
 
 
30
cdef extern from "Python.h":
 
31
    ctypedef int Py_ssize_t # Required for older pyrex versions
 
32
    ctypedef struct PyObject:
 
33
        pass
 
34
    int PyTuple_CheckExact(object p)
 
35
    Py_ssize_t PyTuple_GET_SIZE(object t)
 
36
    int PyString_CheckExact(object)
 
37
    char *PyString_AS_STRING(object s)
 
38
    PyObject *PyString_FromStringAndSize_ptr "PyString_FromStringAndSize" (char *, Py_ssize_t)
 
39
    Py_ssize_t PyString_GET_SIZE(object)
 
40
    void PyString_InternInPlace(PyObject **)
 
41
    long PyInt_AS_LONG(object)
 
42
 
 
43
    int PyDict_SetItem(object d, object k, object v) except -1
 
44
 
 
45
    void Py_INCREF(object)
 
46
    void Py_DECREF_ptr "Py_DECREF" (PyObject *)
 
47
 
 
48
    object PyString_FromStringAndSize(char*, Py_ssize_t)
61
49
 
62
50
# cimport all of the definitions we will need to access
63
 
from .._static_tuple_c cimport (
64
 
    import_static_tuple_c,
65
 
    StaticTuple,
66
 
    StaticTuple_New,
67
 
    StaticTuple_Intern,
68
 
    StaticTuple_SET_ITEM,
69
 
    StaticTuple_CheckExact,
70
 
    StaticTuple_GET_SIZE,
71
 
    )
 
51
from _static_tuple_c cimport StaticTuple,\
 
52
    import_static_tuple_c, StaticTuple_New, \
 
53
    StaticTuple_Intern, StaticTuple_SET_ITEM, StaticTuple_CheckExact, \
 
54
    StaticTuple_GET_SIZE
 
55
 
 
56
cdef object crc32
 
57
from zlib import crc32
 
58
 
72
59
 
73
60
# Set up the StaticTuple C_API functionality
74
61
import_static_tuple_c()
75
62
 
76
 
cdef object crc32
77
 
from zlib import crc32
78
 
 
79
63
cdef object _LeafNode
80
64
_LeafNode = None
81
65
cdef object _InternalNode
83
67
cdef object _unknown
84
68
_unknown = None
85
69
 
 
70
# We shouldn't just copy this from _dirstate_helpers_pyx
 
71
cdef void* _my_memrchr(void *s, int c, size_t n): # cannot_raise
 
72
    # memrchr seems to be a GNU extension, so we have to implement it ourselves
 
73
    cdef char *pos
 
74
    cdef char *start
 
75
 
 
76
    start = <char*>s
 
77
    pos = start + n - 1
 
78
    while pos >= start:
 
79
        if pos[0] == c:
 
80
            return <void*>pos
 
81
        pos = pos - 1
 
82
    return NULL
 
83
 
 
84
 
 
85
cdef object safe_interned_string_from_size(char *s, Py_ssize_t size):
 
86
    cdef PyObject *py_str
 
87
    if size < 0:
 
88
        raise AssertionError(
 
89
            'tried to create a string with an invalid size: %d @0x%x'
 
90
            % (size, <int>s))
 
91
    py_str = PyString_FromStringAndSize_ptr(s, size)
 
92
    PyString_InternInPlace(&py_str)
 
93
    result = <object>py_str
 
94
    # Casting a PyObject* to an <object> triggers an INCREF from Pyrex, so we
 
95
    # DECREF it to avoid geting immortal strings
 
96
    Py_DECREF_ptr(py_str)
 
97
    return result
 
98
 
86
99
 
87
100
def _search_key_16(key):
88
101
    """See chk_map._search_key_16."""
96
109
    num_bits = len(key)
97
110
    # 4 bytes per crc32, and another 1 byte between bits
98
111
    num_out_bytes = (9 * num_bits) - 1
99
 
    out = PyBytes_FromStringAndSize(NULL, num_out_bytes)
100
 
    c_out = PyBytes_AS_STRING(out)
 
112
    out = PyString_FromStringAndSize(NULL, num_out_bytes)
 
113
    c_out = PyString_AS_STRING(out)
101
114
    for i from 0 <= i < num_bits:
102
115
        if i > 0:
103
116
            c_out[0] = c'\x00'
104
117
            c_out = c_out + 1
105
 
        crc_val = PyInt_AsUnsignedLongMask(crc32(key[i])) & 0xFFFFFFFFUL
 
118
        crc_val = PyInt_AS_LONG(crc32(key[i]))
106
119
        # Hex(val) order
107
 
        sprintf(c_out, '%08lX', crc_val)
 
120
        sprintf(c_out, '%08X', crc_val)
108
121
        c_out = c_out + 8
109
122
    return out
110
123
 
121
134
    num_bits = len(key)
122
135
    # 4 bytes per crc32, and another 1 byte between bits
123
136
    num_out_bytes = (5 * num_bits) - 1
124
 
    out = PyBytes_FromStringAndSize(NULL, num_out_bytes)
125
 
    c_out = PyBytes_AS_STRING(out)
 
137
    out = PyString_FromStringAndSize(NULL, num_out_bytes)
 
138
    c_out = PyString_AS_STRING(out)
126
139
    for i from 0 <= i < num_bits:
127
140
        if i > 0:
128
141
            c_out[0] = c'\x00'
129
142
            c_out = c_out + 1
130
 
        crc_val = PyInt_AsUnsignedLongMask(crc32(key[i]))
 
143
        crc_val = PyInt_AS_LONG(crc32(key[i]))
131
144
        # MSB order
132
145
        c_out[0] = (crc_val >> 24) & 0xFF
133
146
        c_out[1] = (crc_val >> 16) & 0xFF
149
162
    :return: The integer stored in those bytes
150
163
    """
151
164
    cdef int value
152
 
    cdef char *next_line
153
 
    cdef char *next_int
 
165
    cdef char *next_line, *next
154
166
 
155
167
    next_line = <char *>memchr(cur[0], c'\n', end - cur[0])
156
168
    if next_line == NULL:
157
169
        raise ValueError("Missing %s line\n" % message)
158
170
 
159
 
    value = strtol(cur[0], &next_int, 10)
160
 
    if next_int != next_line:
 
171
    value = strtol(cur[0], &next, 10)
 
172
    if next != next_line:
161
173
        raise ValueError("%s line not a proper int\n" % message)
162
174
    cur[0] = next_line + 1
163
175
    return value
167
179
    """Set the global attributes. Done lazy to avoid recursive import loops."""
168
180
    global _LeafNode, _InternalNode, _unknown
169
181
 
170
 
    from . import chk_map
 
182
    from bzrlib import chk_map
171
183
    _LeafNode = chk_map.LeafNode
172
184
    _InternalNode = chk_map.InternalNode
173
185
    _unknown = chk_map._unknown
174
186
 
175
187
 
176
 
def _deserialise_leaf_node(data, key, search_key_func=None):
 
188
def _deserialise_leaf_node(bytes, key, search_key_func=None):
177
189
    """Deserialise bytes, with key key, into a LeafNode.
178
190
 
179
191
    :param bytes: The bytes of the node.
180
192
    :param key: The key that the serialised node has.
181
193
    """
182
 
    cdef char *c_bytes
183
 
    cdef char *cur
184
 
    cdef char *next
185
 
    cdef char *end
 
194
    cdef char *c_bytes, *cur, *next, *end
186
195
    cdef char *next_line
187
196
    cdef Py_ssize_t c_bytes_len, prefix_length, items_length
188
197
    cdef int maximum_size, width, length, i, prefix_tail_len
189
198
    cdef int num_value_lines, num_prefix_bits
190
 
    cdef char *prefix
191
 
    cdef char *value_start
192
 
    cdef char *prefix_tail
193
 
    cdef char *next_null
194
 
    cdef char *last_null
195
 
    cdef char *line_start
196
 
    cdef char *c_entry
197
 
    cdef char *entry_start
 
199
    cdef char *prefix, *value_start, *prefix_tail
 
200
    cdef char *next_null, *last_null, *line_start
 
201
    cdef char *c_entry, *entry_start
198
202
    cdef StaticTuple entry_bits
199
203
 
200
204
    if _LeafNode is None:
203
207
    result = _LeafNode(search_key_func=search_key_func)
204
208
    # Splitlines can split on '\r' so don't use it, split('\n') adds an
205
209
    # extra '' if the bytes ends in a final newline.
206
 
    if not PyBytes_CheckExact(data):
207
 
        raise TypeError('expected bytes not %s' % (type(data),))
208
 
 
209
 
    c_bytes = PyBytes_AS_STRING(data)
210
 
    c_bytes_len = PyBytes_GET_SIZE(data)
211
 
 
212
 
    if c_bytes_len < 9 or memcmp(c_bytes, b"chkleaf:\n", 9) != 0:
213
 
        raise ValueError("not a serialised leaf node: %r" % data)
 
210
    if not PyString_CheckExact(bytes):
 
211
        raise TypeError('bytes must be a plain string not %s' % (type(bytes),))
 
212
 
 
213
    c_bytes = PyString_AS_STRING(bytes)
 
214
    c_bytes_len = PyString_GET_SIZE(bytes)
 
215
 
 
216
    if c_bytes_len < 9 or memcmp(c_bytes, "chkleaf:\n", 9) != 0:
 
217
        raise ValueError("not a serialised leaf node: %r" % bytes)
214
218
    if c_bytes[c_bytes_len - 1] != c'\n':
215
219
        raise ValueError("bytes does not end in a newline")
216
220
 
234
238
    while next_null != NULL:
235
239
        num_prefix_bits = num_prefix_bits + 1
236
240
        prefix_bits.append(
237
 
            PyBytes_FromStringAndSize(prefix_tail, next_null - prefix_tail))
 
241
            PyString_FromStringAndSize(prefix_tail, next_null - prefix_tail))
238
242
        prefix_tail = next_null + 1
239
243
        next_null = <char *>memchr(prefix_tail, c'\0', next_line - prefix_tail)
240
244
    prefix_tail_len = next_line - prefix_tail
271
275
            # SET_ITEM 'steals' a reference
272
276
            Py_INCREF(entry)
273
277
            StaticTuple_SET_ITEM(entry_bits, i, entry)
274
 
        value = PyBytes_FromStringAndSize(value_start, next_line - value_start)
 
278
        value = PyString_FromStringAndSize(value_start, next_line - value_start)
275
279
        # The next entry bit needs the 'tail' from the prefix, and first part
276
280
        # of the line
277
281
        entry_start = line_start
279
283
                                   last_null - entry_start + 1)
280
284
        if next_null == NULL:
281
285
            raise ValueError('bad no null, bad')
282
 
        entry = PyBytes_FromStringAndSize(
283
 
            NULL, prefix_tail_len + next_null - line_start)
284
 
        c_entry = PyBytes_AS_STRING(entry)
 
286
        entry = PyString_FromStringAndSize(NULL,
 
287
                    prefix_tail_len + next_null - line_start)
 
288
        c_entry = PyString_AS_STRING(entry)
285
289
        if prefix_tail_len > 0:
286
290
            memcpy(c_entry, prefix_tail, prefix_tail_len)
287
291
        if next_null - line_start > 0:
298
302
                                       last_null - entry_start + 1)
299
303
            if next_null == NULL:
300
304
                raise ValueError('bad no null')
301
 
            entry = PyBytes_FromStringAndSize(
302
 
                entry_start, next_null - entry_start)
 
305
            entry = PyString_FromStringAndSize(entry_start,
 
306
                                               next_null - entry_start)
303
307
            Py_INCREF(entry)
304
308
            StaticTuple_SET_ITEM(entry_bits, i, entry)
305
309
        if StaticTuple_GET_SIZE(entry_bits) != width:
322
326
        result._common_serialised_prefix = None
323
327
    else:
324
328
        result._search_prefix = _unknown
325
 
        result._common_serialised_prefix = PyBytes_FromStringAndSize(
326
 
            prefix, prefix_length)
 
329
        result._common_serialised_prefix = PyString_FromStringAndSize(prefix,
 
330
                                                prefix_length)
327
331
    if c_bytes_len != result._current_size():
328
332
        raise AssertionError('_current_size computed incorrectly %d != %d',
329
333
            c_bytes_len, result._current_size())
330
334
    return result
331
335
 
332
336
 
333
 
def _deserialise_internal_node(data, key, search_key_func=None):
334
 
    cdef char *c_bytes
335
 
    cdef char *cur
336
 
    cdef char *end
 
337
def _deserialise_internal_node(bytes, key, search_key_func=None):
 
338
    cdef char *c_bytes, *cur, *next, *end
337
339
    cdef char *next_line
338
340
    cdef Py_ssize_t c_bytes_len, prefix_length
339
341
    cdef int maximum_size, width, length, i, prefix_tail_len
340
 
    cdef char *prefix
341
 
    cdef char *line_prefix
342
 
    cdef char *next_null
343
 
    cdef char *c_item_prefix
 
342
    cdef char *prefix, *line_prefix, *next_null, *c_item_prefix
344
343
 
345
344
    if _InternalNode is None:
346
345
        _import_globals()
348
347
 
349
348
    if not StaticTuple_CheckExact(key):
350
349
        raise TypeError('key %r is not a StaticTuple' % (key,))
351
 
    if not PyBytes_CheckExact(data):
352
 
        raise TypeError('expected bytes not %s' % (type(data),))
353
 
 
354
 
    c_bytes = PyBytes_AS_STRING(data)
355
 
    c_bytes_len = PyBytes_GET_SIZE(data)
356
 
 
357
 
    if c_bytes_len < 9 or memcmp(c_bytes, b"chknode:\n", 9) != 0:
358
 
        raise ValueError("not a serialised internal node: %r" % data)
 
350
    if not PyString_CheckExact(bytes):
 
351
        raise TypeError('bytes must be a plain string not %s' % (type(bytes),))
 
352
 
 
353
    c_bytes = PyString_AS_STRING(bytes)
 
354
    c_bytes_len = PyString_GET_SIZE(bytes)
 
355
 
 
356
    if c_bytes_len < 9 or memcmp(c_bytes, "chknode:\n", 9) != 0:
 
357
        raise ValueError("not a serialised internal node: %r" % bytes)
359
358
    if c_bytes[c_bytes_len - 1] != c'\n':
360
359
        raise ValueError("bytes does not end in a newline")
361
360
 
381
380
        next_null = <char *>_my_memrchr(cur, c'\0', next_line - cur)
382
381
        if next_null == NULL:
383
382
            raise ValueError('bad no null')
384
 
        item_prefix = PyBytes_FromStringAndSize(
385
 
            NULL, prefix_length + next_null - cur)
386
 
        c_item_prefix = PyBytes_AS_STRING(item_prefix)
 
383
        item_prefix = PyString_FromStringAndSize(NULL,
 
384
            prefix_length + next_null - cur)
 
385
        c_item_prefix = PyString_AS_STRING(item_prefix)
387
386
        if prefix_length:
388
387
            memcpy(c_item_prefix, prefix, prefix_length)
389
388
        memcpy(c_item_prefix + prefix_length, cur, next_null - cur)
390
 
        flat_key = PyBytes_FromStringAndSize(
391
 
            next_null + 1, next_line - next_null - 1)
 
389
        flat_key = PyString_FromStringAndSize(next_null + 1,
 
390
                                              next_line - next_null - 1)
392
391
        flat_key = StaticTuple(flat_key).intern()
393
392
        PyDict_SetItem(items, item_prefix, flat_key)
394
393
        cur = next_line + 1
400
399
    result._key_width = width
401
400
    # XXX: InternalNodes don't really care about their size, and this will
402
401
    #      change if we add prefix compression
403
 
    result._raw_size = None
 
402
    result._raw_size = None # len(bytes)
404
403
    result._node_width = len(item_prefix)
405
 
    result._search_prefix = PyBytes_FromStringAndSize(prefix, prefix_length)
 
404
    result._search_prefix = PyString_FromStringAndSize(prefix, prefix_length)
406
405
    return result
407
406
 
408
407
 
409
 
def _bytes_to_text_key(data):
 
408
def _bytes_to_text_key(bytes):
410
409
    """Take a CHKInventory value string and return a (file_id, rev_id) tuple"""
411
410
    cdef StaticTuple key
412
 
    cdef char *byte_str
413
 
    cdef char *cur_end
414
 
    cdef char *file_id_str
415
 
    cdef char *byte_end
 
411
    cdef char *byte_str, *cur_end, *file_id_str, *byte_end
416
412
    cdef char *revision_str
417
413
    cdef Py_ssize_t byte_size, pos, file_id_len
418
414
 
419
 
    if not PyBytes_CheckExact(data):
420
 
        raise TypeError('expected bytes not %s' % (type(data),))
421
 
    byte_str = PyBytes_AS_STRING(data)
422
 
    byte_size = PyBytes_GET_SIZE(data)
 
415
    if not PyString_CheckExact(bytes):
 
416
        raise TypeError('bytes must be a string')
 
417
    byte_str = PyString_AS_STRING(bytes)
 
418
    byte_size = PyString_GET_SIZE(bytes)
423
419
    byte_end = byte_str + byte_size
424
420
    cur_end = <char*>memchr(byte_str, c':', byte_size)
425
421
    if cur_end == NULL:
426
422
        raise ValueError('No kind section found.')
427
423
    if cur_end[1] != c' ':
428
 
        raise ValueError(
429
 
            'Kind section should end with ": ", got %r' % str(cur_end[:2],))
 
424
        raise ValueError('Kind section should end with ": "')
430
425
    file_id_str = cur_end + 2
431
426
    # file_id is now the data up until the next newline
432
427
    cur_end = <char*>memchr(file_id_str, c'\n', byte_end - file_id_str)
452
447
        cur_end - revision_str)
453
448
    key = StaticTuple_New(2)
454
449
    Py_INCREF(file_id)
455
 
    StaticTuple_SET_ITEM(key, 0, file_id)
 
450
    StaticTuple_SET_ITEM(key, 0, file_id) 
456
451
    Py_INCREF(revision)
457
 
    StaticTuple_SET_ITEM(key, 1, revision)
 
452
    StaticTuple_SET_ITEM(key, 1, revision) 
458
453
    return StaticTuple_Intern(key)