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)
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)
64
63
cdef class KnitIndexReader:
91
90
if not PyList_CheckExact(self.history):
92
91
raise TypeError('kndx._history must be a python list')
94
cdef char * _end_of_option(self, char *option_str, char *end):
95
"""Find the end of this option string.
97
This is similar to doing ``strchr(option_str, ',')``, except
98
it knows to stop if it hits 'end' first.
104
if cur[0] == c',' or cur[0] == c' ':
109
93
cdef object process_options(self, char *option_str, char *end):
110
94
"""Process the options string into a list."""
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
113
101
# options = PyString_FromStringAndSize(option_str,
115
103
# return options.split(',')
117
105
final_options = []
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
125
next = self._end_of_option(option_str, end)
108
next = <char*>memchr(option_str, c',', end - option_str)
126
111
next_option = PyString_FromStringAndSize(option_str,
127
112
next - option_str)
128
113
PyList_Append(final_options, next_option)
148
135
# return real_parents
151
while parent_str <= end and parent_str != NULL:
152
# strchr is safe here, because our lines always end
154
next = strchr(parent_str, c' ')
138
if parent_str == NULL:
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:
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,
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
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:
212
200
# Move past the space character
213
201
option_str = option_str + 1
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:
219
207
option_end = pos_str
220
208
pos_str = pos_str + 1
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:
226
214
size_str = size_str + 1
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
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)
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)