~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_knit_load_data_c.pyx

  • Committer: John Arbash Meinel
  • Date: 2007-06-29 15:39:01 UTC
  • mto: This revision was merged to the branch mainline in revision 2614.
  • Revision ID: john@arbash-meinel.com-20070629153901-nxydiwh8t8ug76yl
Switch from strchr to memchr to ensure we never search all of memory.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 
23
23
 
24
24
cdef extern from "stdlib.h":
 
25
    ctypedef unsigned size_t
25
26
    long int strtol(char *nptr, char **endptr, int base)
26
27
    unsigned long int strtoul(char *nptr, char **endptr, int base)
27
28
 
56
57
 
57
58
 
58
59
cdef extern from "string.h":
59
 
    char *strchr(char *s1, char c)
60
 
    int strncmp(char *s1, char *s2, int len)
61
 
    int strcmp(char *s1, char *s2)
 
60
    void *memchr(void *s, int c, size_t n)
62
61
 
63
62
 
64
63
cdef class KnitIndexReader:
91
90
        if not PyList_CheckExact(self.history):
92
91
            raise TypeError('kndx._history must be a python list')
93
92
 
94
 
    cdef char * _end_of_option(self, char *option_str, char *end):
95
 
        """Find the end of this option string.
96
 
 
97
 
        This is similar to doing ``strchr(option_str, ',')``, except
98
 
        it knows to stop if it hits 'end' first.
99
 
        """
100
 
        cdef char * cur
101
 
 
102
 
        cur = option_str
103
 
        while cur < end:
104
 
            if cur[0] == c',' or cur[0] == c' ':
105
 
                return cur
106
 
            cur = cur + 1
107
 
        return end
108
 
 
109
93
    cdef object process_options(self, char *option_str, char *end):
110
94
        """Process the options string into a list."""
111
95
        cdef char *next
112
96
 
 
97
        # This is alternative code which creates a python string and splits it.
 
98
        # It is "correct" and more obvious, but slower than the following code.
 
99
        # It can be uncommented to switch in case the other code is seen as
 
100
        # suspect.
113
101
        # options = PyString_FromStringAndSize(option_str,
114
 
        #                                      end-option_str)
 
102
        #                                      end - option_str)
115
103
        # return options.split(',')
116
104
 
117
105
        final_options = []
118
106
 
119
107
        while option_str < end:
120
 
            # Using strchr here actually hurts performance dramatically.
121
 
            # Because you aren't guaranteed to have a ',' any time soon,
122
 
            # so it may have to search for a long time.
123
 
            # The closest function is memchr, but that seems to be a
124
 
            # GNU extension.
125
 
            next = self._end_of_option(option_str, end)
 
108
            next = <char*>memchr(option_str, c',', end - option_str)
 
109
            if next == NULL:
 
110
                next = end
126
111
            next_option = PyString_FromStringAndSize(option_str,
127
112
                                                     next - option_str)
128
113
            PyList_Append(final_options, next_option)
137
122
        cdef int int_parent
138
123
        cdef char *parent_end
139
124
 
 
125
        # Alternative, correct but slower code.
 
126
        #
140
127
        # parents = PyString_FromStringAndSize(parent_str,
141
128
        #                                      end - parent_str)
142
129
        # real_parents = []
148
135
        # return real_parents
149
136
 
150
137
        parents = []
151
 
        while parent_str <= end and parent_str != NULL:
152
 
            # strchr is safe here, because our lines always end
153
 
            # with ' :'
154
 
            next = strchr(parent_str, c' ')
 
138
        if parent_str == NULL:
 
139
            return []
 
140
        while parent_str <= end:
 
141
            next = <char*>memchr(parent_str, c' ', end - parent_str)
155
142
            if next == NULL or next >= end or next == parent_str:
156
143
                break
157
144
 
158
145
            if parent_str[0] == c'.':
159
146
                # This is an explicit revision id
160
147
                parent_str = parent_str + 1
161
 
                parent = PyString_FromStringAndSize(parent_str, next-parent_str)
 
148
                parent = PyString_FromStringAndSize(parent_str,
 
149
                                                    next - parent_str)
162
150
            else:
163
151
                # This in an integer mapping to original
164
152
                # TODO: ensure that we are actually parsing the string
204
192
        cdef void *cache_entry
205
193
 
206
194
        version_id_str = start
207
 
        option_str = strchr(version_id_str, c' ')
 
195
        option_str = <char*>memchr(version_id_str, c' ', end - version_id_str)
208
196
        if option_str == NULL or option_str >= end:
209
197
            # Short entry
210
198
            return 0
212
200
        # Move past the space character
213
201
        option_str = option_str + 1
214
202
 
215
 
        pos_str = strchr(option_str, c' ')
 
203
        pos_str = <char*>memchr(option_str, c' ', end - option_str)
216
204
        if pos_str == NULL or pos_str >= end:
217
205
            # Short entry
218
206
            return 0
219
207
        option_end = pos_str
220
208
        pos_str = pos_str + 1
221
209
 
222
 
        size_str = strchr(pos_str, c' ')
 
210
        size_str = <char*>memchr(pos_str, c' ', end - pos_str)
223
211
        if size_str == NULL or size_str >= end:
224
212
            # Short entry
225
213
            return 0
226
214
        size_str = size_str + 1
227
215
 
228
216
        # TODO: Make sure this works when there are no parents
229
 
        parent_str = strchr(size_str, c' ')
 
217
        parent_str = <char*>memchr(size_str, c' ', end - size_str)
230
218
        if parent_str == NULL or parent_str >= end:
231
219
            # Missing parents
232
220
            return 0
272
260
 
273
261
        start = self.cur_str
274
262
        # Find the next newline
275
 
        last = strchr(start, c'\n')
 
263
        last = <char*>memchr(start, c'\n', self.end_str - start)
276
264
        if last == NULL:
277
265
            # Process until the end of the file
278
 
            last = self.end_str-1
 
266
            last = self.end_str - 1
279
267
            self.cur_str = self.end_str
280
268
            line = PyString_FromStringAndSize(start, last - start)
281
269
            ending = PyString_FromStringAndSize(last, 1)