/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 breezy/bzr/_groupcompress_pyx.pyx

  • Committer: Jelmer Vernooij
  • Date: 2018-11-16 23:15:15 UTC
  • mfrom: (7180 work)
  • mto: This revision was merged to the branch mainline in revision 7183.
  • Revision ID: jelmer@jelmer.uk-20181116231515-zqd2yn6kj8lfydyp
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
cdef extern from "python-compat.h":
23
23
    pass
24
24
 
25
 
 
26
 
cdef extern from "Python.h":
27
 
    ctypedef struct PyObject:
28
 
        pass
29
 
    int PyBytes_CheckExact(object)
30
 
    char * PyBytes_AS_STRING(object)
31
 
    Py_ssize_t PyBytes_GET_SIZE(object)
32
 
    object PyBytes_FromStringAndSize(char *, Py_ssize_t)
33
 
 
34
 
 
35
 
cdef extern from *:
36
 
    ctypedef unsigned long size_t
37
 
    void * malloc(size_t) nogil
38
 
    void * realloc(void *, size_t) nogil
39
 
    void free(void *) nogil
40
 
    void memcpy(void *, void *, size_t) nogil
 
25
from libc.stdlib cimport (
 
26
    free,
 
27
    )
 
28
from libc.string cimport (
 
29
    memcpy,
 
30
    )
 
31
 
 
32
from cpython.bytes cimport (
 
33
    PyBytes_AS_STRING,
 
34
    PyBytes_CheckExact,
 
35
    PyBytes_FromStringAndSize,
 
36
    PyBytes_GET_SIZE,
 
37
    )
 
38
from cpython.object cimport (
 
39
    PyObject,
 
40
    )
 
41
from cpython.mem cimport (
 
42
    PyMem_Free,
 
43
    PyMem_Malloc,
 
44
    )
41
45
 
42
46
 
43
47
cdef extern from "delta.h":
78
82
    unsigned int rabin_hash (unsigned char *data)
79
83
 
80
84
 
81
 
cdef void *safe_malloc(size_t count) except NULL:
82
 
    cdef void *result
83
 
    result = malloc(count)
84
 
    if result == NULL:
85
 
        raise MemoryError('Failed to allocate %d bytes of memory' % (count,))
86
 
    return result
87
 
 
88
 
 
89
 
cdef void *safe_realloc(void * old, size_t count) except NULL:
90
 
    cdef void *result
91
 
    result = realloc(old, count)
92
 
    if result == NULL:
93
 
        raise MemoryError('Failed to reallocate to %d bytes of memory'
94
 
                          % (count,))
95
 
    return result
96
 
 
97
 
 
98
 
cdef int safe_free(void **val) except -1:
99
 
    assert val != NULL
100
 
    if val[0] != NULL:
101
 
        free(val[0])
102
 
        val[0] = NULL
103
 
 
104
85
def make_delta_index(source):
105
86
    return DeltaIndex(source)
106
87
 
130
111
 
131
112
cdef class DeltaIndex:
132
113
 
133
 
    # We need Pyrex 0.9.8+ to understand a 'list' definition, and this object
134
 
    # isn't performance critical
135
 
    # cdef readonly list _sources
136
 
    cdef readonly object _sources
 
114
    cdef readonly list _sources
137
115
    cdef source_info *_source_infos
138
116
    cdef delta_index *_index
139
117
    cdef public unsigned long _source_offset
144
122
        self._sources = []
145
123
        self._index = NULL
146
124
        self._max_num_sources = 65000
147
 
        self._source_infos = <source_info *>safe_malloc(sizeof(source_info)
148
 
                                                        * self._max_num_sources)
 
125
        self._source_infos = <source_info *>PyMem_Malloc(
 
126
            sizeof(source_info) * self._max_num_sources)
 
127
        if self._source_infos == NULL:
 
128
            raise MemoryError('failed to allocate memory for DeltaIndex')
149
129
        self._source_offset = 0
150
130
        self._max_bytes_to_index = 0
151
131
        if max_bytes_to_index is not None:
157
137
    def __sizeof__(self):
158
138
        # We want to track the _source_infos allocations, but the referenced
159
139
        # void* are actually tracked in _sources itself.
160
 
        # XXX: Cython is capable of doing sizeof(class) and returning the size
161
 
        #      of the underlying struct. Pyrex (<= 0.9.9) refuses, so we need
162
 
        #      to do it manually. *sigh* Note that we might get it wrong
163
 
        #      because of alignment issues.
164
 
        cdef Py_ssize_t size
165
 
        # PyObject start, vtable *, 3 object pointers, 2 C ints
166
 
        size = ((sizeof(PyObject) + sizeof(void*) + 3*sizeof(PyObject*)
167
 
                 + sizeof(unsigned long)
168
 
                 + sizeof(unsigned int))
 
140
        return (sizeof(DeltaIndex)
169
141
                + (sizeof(source_info) * self._max_num_sources)
170
142
                + sizeof_delta_index(self._index))
171
 
        return size
172
143
 
173
144
    def __repr__(self):
174
145
        return '%s(%d, %d)' % (self.__class__.__name__,
178
149
        if self._index != NULL:
179
150
            free_delta_index(self._index)
180
151
            self._index = NULL
181
 
        safe_free(<void **>&self._source_infos)
 
152
        PyMem_Free(self._source_infos)
182
153
 
183
154
    def _has_index(self):
184
155
        return (self._index != NULL)
326
297
    cdef _expand_sources(self):
327
298
        raise RuntimeError('if we move self._source_infos, then we need to'
328
299
                           ' change all of the index pointers as well.')
329
 
        self._max_num_sources = self._max_num_sources * 2
330
 
        self._source_infos = <source_info *>safe_realloc(self._source_infos,
331
 
                                                sizeof(source_info)
332
 
                                                * self._max_num_sources)
333
300
 
334
301
    def make_delta(self, target_bytes, max_delta_size=0):
335
302
        """Create a delta from the current source to the target bytes."""
399
366
    return _apply_delta(source, source_size, delta, delta_size)
400
367
 
401
368
 
402
 
cdef unsigned char *_decode_copy_instruction(unsigned char *bytes,
 
369
cdef unsigned char *_decode_copy_instruction(unsigned char *data,
403
370
    unsigned char cmd, unsigned int *offset,
404
371
    unsigned int *length) nogil: # cannot_raise
405
372
    """Decode a copy instruction from the next few bytes.
417
384
    size = 0
418
385
    count = 0
419
386
    if (cmd & 0x01):
420
 
        off = bytes[count]
 
387
        off = data[count]
421
388
        count = count + 1
422
389
    if (cmd & 0x02):
423
 
        off = off | (bytes[count] << 8)
 
390
        off = off | (data[count] << 8)
424
391
        count = count + 1
425
392
    if (cmd & 0x04):
426
 
        off = off | (bytes[count] << 16)
 
393
        off = off | (data[count] << 16)
427
394
        count = count + 1
428
395
    if (cmd & 0x08):
429
 
        off = off | (bytes[count] << 24)
 
396
        off = off | (data[count] << 24)
430
397
        count = count + 1
431
398
    if (cmd & 0x10):
432
 
        size = bytes[count]
 
399
        size = data[count]
433
400
        count = count + 1
434
401
    if (cmd & 0x20):
435
 
        size = size | (bytes[count] << 8)
 
402
        size = size | (data[count] << 8)
436
403
        count = count + 1
437
404
    if (cmd & 0x40):
438
 
        size = size | (bytes[count] << 16)
 
405
        size = size | (data[count] << 16)
439
406
        count = count + 1
440
407
    if (size == 0):
441
408
        size = 0x10000
442
409
    offset[0] = off
443
410
    length[0] = size
444
 
    return bytes + count
 
411
    return data + count
445
412
 
446
413
 
447
414
cdef object _apply_delta(char *source, Py_ssize_t source_size,
448
415
                         char *delta, Py_ssize_t delta_size):
449
416
    """common functionality between apply_delta and apply_delta_to_source."""
450
 
    cdef unsigned char *data, *top
451
 
    cdef unsigned char *dst_buf, *out, cmd
 
417
    cdef unsigned char *data
 
418
    cdef unsigned char *top
 
419
    cdef unsigned char *dst_buf
 
420
    cdef unsigned char *out
 
421
    cdef unsigned char cmd
452
422
    cdef Py_ssize_t size
453
423
    cdef unsigned int cp_off, cp_size
454
424
    cdef int failed
510
480
        raise RuntimeError('Did not extract the number of bytes we expected'
511
481
            ' we were left with %d bytes in "size", and top - data = %d'
512
482
            % (size, <int>(top - data)))
513
 
        return None
514
483
 
515
484
    # *dst_size = out - dst_buf;
516
485
    if (out - dst_buf) != PyBytes_GET_SIZE(result):
567
536
    return PyBytes_FromStringAndSize(<char *>c_bytes, count)
568
537
 
569
538
 
570
 
def decode_base128_int(bytes):
 
539
def decode_base128_int(data):
571
540
    """Decode an integer from a 7-bit lsb encoding."""
572
541
    cdef int offset
573
542
    cdef int val
579
548
    offset = 0
580
549
    val = 0
581
550
    shift = 0
582
 
    if not PyBytes_CheckExact(bytes):
 
551
    if not PyBytes_CheckExact(data):
583
552
        raise TypeError('bytes is not a string')
584
 
    c_bytes = <unsigned char*>PyBytes_AS_STRING(bytes)
 
553
    c_bytes = <unsigned char*>PyBytes_AS_STRING(data)
585
554
    # We take off 1, because we have to be able to decode the non-expanded byte
586
 
    num_low_bytes = PyBytes_GET_SIZE(bytes) - 1
 
555
    num_low_bytes = PyBytes_GET_SIZE(data) - 1
587
556
    while (c_bytes[offset] & 0x80) and offset < num_low_bytes:
588
557
        val = val | ((c_bytes[offset] & 0x7F) << shift)
589
558
        shift = shift + 7