~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to _groupcompress_pyx.pyx

  • Committer: John Arbash Meinel
  • Date: 2009-03-03 16:31:07 UTC
  • mto: (0.17.31 trunk)
  • mto: This revision was merged to the branch mainline in revision 4280.
  • Revision ID: john@arbash-meinel.com-20090303163107-l4j0114btw2efmjp
Change the code around again.

This time, the information about sources is maintained in the DeltaIndex object.
And we pass that info down into create_delta_index, et al.

Next step is to actually combine the delta indexes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
    void memcpy(void *, void *, size_t)
25
25
 
26
26
cdef extern from "delta.h":
 
27
    struct source_info:
 
28
        void *buf
 
29
        unsigned long size
 
30
        unsigned long agg_offset
27
31
    struct delta_index:
28
32
        unsigned long memsize
29
33
        void *src_buf
30
34
        unsigned long src_size
31
35
        unsigned int hash_mask
32
36
        # struct index_entry *hash[]
33
 
    delta_index * create_delta_index(void *buf, unsigned long bufsize, unsigned
34
 
                                     long agg_src_offset)
 
37
    delta_index * create_delta_index(source_info *src)
35
38
    void free_delta_index(delta_index *index)
36
39
    void *create_delta(delta_index **indexes,
37
40
             unsigned int num_indexes,
84
87
    # isn't performance critical
85
88
    # cdef readonly list _sources
86
89
    cdef readonly object _sources
 
90
    cdef source_info *_source_infos
87
91
    cdef delta_index **_indexes
88
92
    cdef readonly unsigned int _num_indexes
89
93
    cdef readonly unsigned int _max_num_indexes
 
94
    cdef readonly unsigned int _max_num_sources
90
95
    cdef public unsigned long _source_offset
91
96
 
92
97
    def __repr__(self):
99
104
        self._max_num_indexes = 1024
100
105
        self._indexes = <delta_index**>safe_malloc(sizeof(delta_index*)
101
106
                                                   * self._max_num_indexes)
 
107
        self._max_num_sources = 1024
 
108
        self._source_infos = <source_info *>safe_malloc(sizeof(source_info)
 
109
                                                        * self._max_num_sources)
102
110
        self._num_indexes = 0
103
111
        self._source_offset = 0
104
112
 
107
115
 
108
116
    def __dealloc__(self):
109
117
        self._ensure_no_indexes()
 
118
        safe_free(<void **>&self._source_infos)
110
119
 
111
120
    def add_source(self, source, unadded_bytes):
112
121
        """Add a new bit of source text to the delta indexes.
118
127
        cdef char *c_source
119
128
        cdef Py_ssize_t c_source_size
120
129
        cdef delta_index *index
 
130
        cdef unsigned int source_location
 
131
        cdef source_info *src
121
132
        cdef unsigned int num_indexes
122
 
        cdef unsigned long agg_src_offset
123
133
 
124
134
        if not PyString_CheckExact(source):
125
135
            raise TypeError('source is not a str')
126
136
 
 
137
        source_location = len(self._sources)
 
138
        if source_location >= self._max_num_sources:
 
139
            self._expand_sources()
127
140
        self._sources.append(source)
128
141
        c_source = PyString_AS_STRING(source)
129
142
        c_source_size = PyString_GET_SIZE(source)
 
143
        src = self._source_infos + source_location
 
144
        src.buf = c_source
 
145
        src.size = c_source_size
130
146
 
131
147
        # TODO: Are usage is ultimately going to be different than the one that
132
148
        #       was originally designed. Specifically, we are going to want to
134
150
        #       fit just fine into the structure. But for now, we just wrap
135
151
        #       create_delta_index (For example, we could always reserve enough
136
152
        #       space to hash a 4MB string, etc.)
137
 
        agg_src_offset = self._source_offset + unadded_bytes
138
 
        index = create_delta_index(c_source, c_source_size, agg_src_offset)
139
 
        self._source_offset = agg_src_offset + c_source_size
 
153
        src.agg_offset = self._source_offset + unadded_bytes
 
154
        index = create_delta_index(src)
 
155
        self._source_offset = src.agg_offset + src.size
140
156
        if index != NULL:
141
157
            num_indexes = self._num_indexes + 1
142
158
            if num_indexes >= self._max_num_indexes:
150
166
                                                sizeof(delta_index *)
151
167
                                                * self._max_num_indexes)
152
168
 
 
169
    cdef _expand_sources(self):
 
170
        self._max_num_sources = self._max_num_sources * 2
 
171
        self._source_infos = <source_info *>safe_realloc(self._source_infos,
 
172
                                                sizeof(source_info)
 
173
                                                * self._max_num_sources)
 
174
 
153
175
    cdef _ensure_no_indexes(self):
154
176
        cdef int i
155
177
 
192
214
 
193
215
 
194
216
def make_delta(source_bytes, target_bytes):
195
 
    """Create a delta from source_bytes => target_bytes."""
196
 
    cdef char *source
197
 
    cdef Py_ssize_t source_size
198
 
    cdef char *target
199
 
    cdef Py_ssize_t target_size
200
 
    cdef delta_index *index
201
 
    cdef void * delta
202
 
    cdef unsigned long delta_size
203
 
    cdef unsigned long max_delta_size
204
 
 
205
 
    max_delta_size = 0 # Unlimited
206
 
 
207
 
    if not PyString_CheckExact(source_bytes):
208
 
        raise TypeError('source is not a str')
209
 
    if not PyString_CheckExact(target_bytes):
210
 
        raise TypeError('target is not a str')
211
 
 
212
 
    source = PyString_AS_STRING(source_bytes)
213
 
    source_size = PyString_GET_SIZE(source_bytes)
214
 
    target = PyString_AS_STRING(target_bytes)
215
 
    target_size = PyString_GET_SIZE(target_bytes)
216
 
 
217
 
    result = None
218
 
    index = create_delta_index(source, source_size, 0)
219
 
    if index != NULL:
220
 
        delta = create_delta(&index, 1, target, target_size,
221
 
                             &delta_size, max_delta_size)
222
 
        free_delta_index(index);
223
 
        if delta:
224
 
            result = PyString_FromStringAndSize(<char *>delta, delta_size)
225
 
            free(delta)
226
 
    return result
 
217
    """Create a delta, this is a wrapper around DeltaIndex.make_delta."""
 
218
    di = DeltaIndex(source_bytes)
 
219
    return di.make_delta(target_bytes)
227
220
 
228
221
 
229
222
def apply_delta(source_bytes, delta_bytes):
341
334
    # *dst_size = out - dst_buf;
342
335
    assert (out - dst_buf) == PyString_GET_SIZE(result)
343
336
    return result
344
 
 
345
 
 
346
 
def apply_delta2(source_bytes, delta_bytes):
347
 
    """Apply a delta generated by make_delta to source_bytes."""
348
 
    # This defers to the patch-delta code rather than implementing it here
349
 
    # If this is faster, we can bring the memory allocation and error handling
350
 
    # into apply_delta(), and leave the primary loop in a separate C func.
351
 
    cdef char *source, *delta, *target
352
 
    cdef Py_ssize_t source_size, delta_size
353
 
    cdef unsigned long target_size
354
 
 
355
 
    if not PyString_CheckExact(source_bytes):
356
 
        raise TypeError('source is not a str')
357
 
    if not PyString_CheckExact(delta_bytes):
358
 
        raise TypeError('delta is not a str')
359
 
 
360
 
    source = PyString_AS_STRING(source_bytes)
361
 
    source_size = PyString_GET_SIZE(source_bytes)
362
 
    delta = PyString_AS_STRING(delta_bytes)
363
 
    delta_size = PyString_GET_SIZE(delta_bytes)
364
 
 
365
 
    target = <char *>patch_delta(source, source_size,
366
 
                                 delta, delta_size,
367
 
                                 &target_size)
368
 
    if target == NULL:
369
 
        return None
370
 
    result = PyString_FromStringAndSize(target, target_size)
371
 
    free(target)
372
 
    return result