source src/oid.c
Line | Flow | Count | Block(s) | Source |
---|---|---|---|---|
1 | - | /* | ||
2 | - | * Copyright (C) the libgit2 contributors. All rights reserved. | ||
3 | - | * | ||
4 | - | * This file is part of libgit2, distributed under the GNU GPL v2 with | ||
5 | - | * a Linking Exception. For full terms see the included COPYING file. | ||
6 | - | */ | ||
7 | - | |||
8 | - | #include "oid.h" | ||
9 | - | |||
10 | - | #include "git2/oid.h" | ||
11 | - | #include "repository.h" | ||
12 | - | #include "global.h" | ||
13 | - | #include <string.h> | ||
14 | - | #include <limits.h> | ||
15 | - | |||
16 | - | static char to_hex[] = "0123456789abcdef"; | ||
17 | - | |||
18 | 1351 | 2 | static int oid_error_invalid(const char *msg) | |
19 | - | { | ||
20 | 1351 | 2 | git_error_set(GIT_ERROR_INVALID, "unable to parse OID - %s", msg); | |
21 | 1351 | 3 | return -1; | |
22 | - | } | ||
23 | - | |||
24 | - | 2 | suppressed: function cannot be solved git_oid_fromstrn (automatic due to inconsistent arc counts in .gcda files)int git_oid_fromstrn(git_oid *out, const char *str, size_t length) | |
25 | - | { | ||
26 | - | size_t p; | ||
27 | - | int v; | ||
28 | - | |||
29 | - | 2-4 | suppressed: function cannot be solved git_oid_fromstrn (automatic due to inconsistent arc counts in .gcda files) assert(out && str); | |
30 | - | |||
31 | - | 5 | suppressed: function cannot be solved git_oid_fromstrn (automatic due to inconsistent arc counts in .gcda files) if (!length) | |
32 | - | 6 | suppressed: function cannot be solved git_oid_fromstrn (automatic due to inconsistent arc counts in .gcda files) return oid_error_invalid("too short"); | |
33 | - | |||
34 | - | 7 | suppressed: function cannot be solved git_oid_fromstrn (automatic due to inconsistent arc counts in .gcda files) if (length > GIT_OID_HEXSZ) | |
35 | - | 8 | suppressed: function cannot be solved git_oid_fromstrn (automatic due to inconsistent arc counts in .gcda files) return oid_error_invalid("too long"); | |
36 | - | |||
37 | - | 9 | suppressed: function cannot be solved git_oid_fromstrn (automatic due to inconsistent arc counts in .gcda files) memset(out->id, 0, GIT_OID_RAWSZ); | |
38 | - | |||
39 | - | 9,16,17 | suppressed: function cannot be solved git_oid_fromstrn (automatic due to inconsistent arc counts in .gcda files) for (p = 0; p < length; p++) { | |
40 | - | 10 | suppressed: function cannot be solved git_oid_fromstrn (automatic due to inconsistent arc counts in .gcda files) v = git__fromhex(str[p]); | |
41 | - | 11 | suppressed: function cannot be solved git_oid_fromstrn (automatic due to inconsistent arc counts in .gcda files) if (v < 0) | |
42 | - | 12 | suppressed: function cannot be solved git_oid_fromstrn (automatic due to inconsistent arc counts in .gcda files) return oid_error_invalid("contains invalid characters"); | |
43 | - | |||
44 | - | 13-15 | suppressed: function cannot be solved git_oid_fromstrn (automatic due to inconsistent arc counts in .gcda files) out->id[p / 2] |= (unsigned char)(v << (p % 2 ? 0 : 4)); | |
45 | - | } | ||
46 | - | |||
47 | - | 18 | suppressed: function cannot be solved git_oid_fromstrn (automatic due to inconsistent arc counts in .gcda files) return 0; | |
48 | - | } | ||
49 | - | |||
50 | 8 | 2 | int git_oid_fromstrp(git_oid *out, const char *str) | |
51 | - | { | ||
52 | 8 | 2 | return git_oid_fromstrn(out, str, strlen(str)); | |
53 | - | } | ||
54 | - | |||
55 | 98948 | 2 | int git_oid_fromstr(git_oid *out, const char *str) | |
56 | - | { | ||
57 | 98948 | 2 | return git_oid_fromstrn(out, str, GIT_OID_HEXSZ); | |
58 | - | } | ||
59 | - | |||
60 | 5657089 | 2 | GIT_INLINE(char) *fmt_one(char *str, unsigned int val) | |
61 | - | { | ||
62 | 5657089 | 2 | *str++ = to_hex[val >> 4]; | |
63 | 5657089 | 2 | *str++ = to_hex[val & 0xf]; | |
64 | 5657089 | 2 | return str; | |
65 | - | } | ||
66 | - | |||
67 | 244416 | 2 | int git_oid_nfmt(char *str, size_t n, const git_oid *oid) | |
68 | - | { | ||
69 | - | size_t i, max_i; | ||
70 | - | |||
71 | 244416 | 2 | if (!oid) { | |
72 | 1 | 3 | memset(str, 0, n); | |
73 | 1 | 3 | return 0; | |
74 | - | } | ||
75 | 244415 | 4 | if (n > GIT_OID_HEXSZ) { | |
76 | 29880 | 5 | memset(&str[GIT_OID_HEXSZ], 0, n - GIT_OID_HEXSZ); | |
77 | 29880 | 5 | n = GIT_OID_HEXSZ; | |
78 | - | } | ||
79 | - | |||
80 | 244415 | 6 | max_i = n / 2; | |
81 | - | |||
82 | 4750308 | 6,8,9 | for (i = 0; i < max_i; i++) | |
83 | 4506009 | 7 | str = fmt_one(str, oid->id[i]); | |
84 | - | |||
85 | 244299 | 10 | if (n & 1) | |
86 | 961 | 11 | *str++ = to_hex[oid->id[i] >> 4]; | |
87 | - | |||
88 | 244299 | 12 | return 0; | |
89 | - | } | ||
90 | - | |||
91 | 4231 | 2 | int git_oid_fmt(char *str, const git_oid *oid) | |
92 | - | { | ||
93 | 4231 | 2 | return git_oid_nfmt(str, GIT_OID_HEXSZ, oid); | |
94 | - | } | ||
95 | - | |||
96 | 66559 | 2 | int git_oid_pathfmt(char *str, const git_oid *oid) | |
97 | - | { | ||
98 | - | size_t i; | ||
99 | - | |||
100 | 66559 | 2 | str = fmt_one(str, oid->id[0]); | |
101 | 72019 | 3 | *str++ = '/'; | |
102 | 1314184 | 3,5,6 | for (i = 1; i < sizeof(oid->id); i++) | |
103 | 1247394 | 4 | str = fmt_one(str, oid->id[i]); | |
104 | - | |||
105 | 66790 | 7 | return 0; | |
106 | - | } | ||
107 | - | |||
108 | 321 | 2 | char *git_oid_tostr_s(const git_oid *oid) | |
109 | - | { | ||
110 | 321 | 2 | char *str = GIT_GLOBAL->oid_fmt; | |
111 | 321 | 3 | git_oid_nfmt(str, GIT_OID_HEXSZ + 1, oid); | |
112 | 321 | 4 | return str; | |
113 | - | } | ||
114 | - | |||
115 | 63 | 2 | char *git_oid_allocfmt(const git_oid *oid) | |
116 | - | { | ||
117 | 63 | 2 | char *str = git__malloc(GIT_OID_HEXSZ + 1); | |
118 | 63 | 3 | if (!str) | |
119 | ##### | 4 | return NULL; | |
120 | 63 | 5 | git_oid_nfmt(str, GIT_OID_HEXSZ + 1, oid); | |
121 | 63 | 6 | return str; | |
122 | - | } | ||
123 | - | |||
124 | - | 2 | suppressed: function cannot be solved git_oid_tostr (automatic due to inconsistent arc counts in .gcda files)char *git_oid_tostr(char *out, size_t n, const git_oid *oid) | |
125 | - | { | ||
126 | - | 2,3 | suppressed: function cannot be solved git_oid_tostr (automatic due to inconsistent arc counts in .gcda files) if (!out || n == 0) | |
127 | - | 4 | suppressed: function cannot be solved git_oid_tostr (automatic due to inconsistent arc counts in .gcda files) return ""; | |
128 | - | |||
129 | - | 5 | suppressed: function cannot be solved git_oid_tostr (automatic due to inconsistent arc counts in .gcda files) if (n > GIT_OID_HEXSZ + 1) | |
130 | - | 6 | suppressed: function cannot be solved git_oid_tostr (automatic due to inconsistent arc counts in .gcda files) n = GIT_OID_HEXSZ + 1; | |
131 | - | |||
132 | - | 7 | suppressed: function cannot be solved git_oid_tostr (automatic due to inconsistent arc counts in .gcda files) git_oid_nfmt(out, n - 1, oid); /* allow room for terminating NUL */ | |
133 | - | 8 | suppressed: function cannot be solved git_oid_tostr (automatic due to inconsistent arc counts in .gcda files) out[n - 1] = '\0'; | |
134 | - | |||
135 | - | 8 | suppressed: function cannot be solved git_oid_tostr (automatic due to inconsistent arc counts in .gcda files) return out; | |
136 | - | } | ||
137 | - | |||
138 | 31233 | 2 | int git_oid__parse( | |
139 | - | git_oid *oid, const char **buffer_out, | ||
140 | - | const char *buffer_end, const char *header) | ||
141 | - | { | ||
142 | 31233 | 2 | const size_t sha_len = GIT_OID_HEXSZ; | |
143 | 31233 | 2 | const size_t header_len = strlen(header); | |
144 | - | |||
145 | 31233 | 2 | const char *buffer = *buffer_out; | |
146 | - | |||
147 | 31233 | 2 | if (buffer + (header_len + sha_len + 1) > buffer_end) | |
148 | 13 | 3 | return -1; | |
149 | - | |||
150 | 31220 | 4 | if (memcmp(buffer, header, header_len) != 0) | |
151 | 11199 | 5 | return -1; | |
152 | - | |||
153 | 20021 | 6 | if (buffer[header_len + sha_len] != '\n') | |
154 | 4 | 7 | return -1; | |
155 | - | |||
156 | 20017 | 8,9 | if (git_oid_fromstr(oid, buffer + header_len) < 0) | |
157 | 3 | 10 | return -1; | |
158 | - | |||
159 | 20014 | 11 | *buffer_out = buffer + (header_len + sha_len + 1); | |
160 | - | |||
161 | 20014 | 11 | return 0; | |
162 | - | } | ||
163 | - | |||
164 | 730 | 2 | void git_oid__writebuf(git_buf *buf, const char *header, const git_oid *oid) | |
165 | - | { | ||
166 | - | char hex_oid[GIT_OID_HEXSZ]; | ||
167 | - | |||
168 | 730 | 2 | git_oid_fmt(hex_oid, oid); | |
169 | 730 | 3 | git_buf_puts(buf, header); | |
170 | 730 | 4 | git_buf_put(buf, hex_oid, GIT_OID_HEXSZ); | |
171 | 730 | 5 | git_buf_putc(buf, '\n'); | |
172 | 730 | 6 | } | |
173 | - | |||
174 | 39177 | 2 | int git_oid_fromraw(git_oid *out, const unsigned char *raw) | |
175 | - | { | ||
176 | 39177 | 2 | memcpy(out->id, raw, sizeof(out->id)); | |
177 | 39177 | 2 | return 0; | |
178 | - | } | ||
179 | - | |||
180 | 816927 | 2 | int git_oid_cpy(git_oid *out, const git_oid *src) | |
181 | - | { | ||
182 | 816927 | 2 | memcpy(out->id, src->id, sizeof(out->id)); | |
183 | 816927 | 2 | return 0; | |
184 | - | } | ||
185 | - | |||
186 | 252091 | 2 | int git_oid_cmp(const git_oid *a, const git_oid *b) | |
187 | - | { | ||
188 | 252091 | 2 | return git_oid__cmp(a, b); | |
189 | - | } | ||
190 | - | |||
191 | 16086557 | 2 | int git_oid_equal(const git_oid *a, const git_oid *b) | |
192 | - | { | ||
193 | 16086557 | 2 | return (git_oid__cmp(a, b) == 0); | |
194 | - | } | ||
195 | - | |||
196 | 125280 | 2 | int git_oid_ncmp(const git_oid *oid_a, const git_oid *oid_b, size_t len) | |
197 | - | { | ||
198 | 125280 | 2 | const unsigned char *a = oid_a->id; | |
199 | 125280 | 2 | const unsigned char *b = oid_b->id; | |
200 | - | |||
201 | 125280 | 2 | if (len > GIT_OID_HEXSZ) | |
202 | 3 | 3 | len = GIT_OID_HEXSZ; | |
203 | - | |||
204 | 162969 | 4,8 | while (len > 1) { | |
205 | 162677 | 5 | if (*a != *b) | |
206 | 124988 | 6 | return 1; | |
207 | 37689 | 7 | a++; | |
208 | 37689 | 7 | b++; | |
209 | 37689 | 7 | len -= 2; | |
210 | - | }; | ||
211 | - | |||
212 | 292 | 9 | if (len) | |
213 | 99 | 10 | if ((*a ^ *b) & 0xf0) | |
214 | 12 | 11 | return 1; | |
215 | - | |||
216 | 280 | 12 | return 0; | |
217 | - | } | ||
218 | - | |||
219 | 167 | 2 | int git_oid_strcmp(const git_oid *oid_a, const char *str) | |
220 | - | { | ||
221 | - | const unsigned char *a; | ||
222 | - | unsigned char strval; | ||
223 | - | int hexval; | ||
224 | - | |||
225 | 3059 | 2,13-15 | for (a = oid_a->id; *str && (a - oid_a->id) < GIT_OID_RAWSZ; ++a) { | |
226 | 2915 | 3,4 | if ((hexval = git__fromhex(*str++)) < 0) | |
227 | 4 | 5 | return -1; | |
228 | 2911 | 6 | strval = (unsigned char)(hexval << 4); | |
229 | 2911 | 6 | if (*str) { | |
230 | 2909 | 7,8 | if ((hexval = git__fromhex(*str++)) < 0) | |
231 | 2 | 9 | return -1; | |
232 | 2907 | 10 | strval |= hexval; | |
233 | - | } | ||
234 | 2909 | 11 | if (*a != strval) | |
235 | 17 | 12 | return (*a - strval); | |
236 | - | } | ||
237 | - | |||
238 | 144 | 16 | return 0; | |
239 | - | } | ||
240 | - | |||
241 | 155 | 2 | int git_oid_streq(const git_oid *oid_a, const char *str) | |
242 | - | { | ||
243 | 155 | 2 | return git_oid_strcmp(oid_a, str) == 0 ? 0 : -1; | |
244 | - | } | ||
245 | - | |||
246 | 356118 | 2 | int git_oid_is_zero(const git_oid *oid_a) | |
247 | - | { | ||
248 | 356118 | 2 | const unsigned char *a = oid_a->id; | |
249 | - | unsigned int i; | ||
250 | 2881436 | 2,5,6 | for (i = 0; i < GIT_OID_RAWSZ; ++i, ++a) | |
251 | 2755185 | 3 | if (*a != 0) | |
252 | 229867 | 4 | return 0; | |
253 | 126251 | 7 | return 1; | |
254 | - | } | ||
255 | - | |||
256 | - | #ifndef GIT_DEPRECATE_HARD | ||
257 | ##### | 2 | int git_oid_iszero(const git_oid *oid_a) | |
258 | - | { | ||
259 | ##### | 2 | return git_oid_is_zero(oid_a); | |
260 | - | } | ||
261 | - | #endif | ||
262 | - | |||
263 | - | typedef short node_index; | ||
264 | - | |||
265 | - | typedef union { | ||
266 | - | const char *tail; | ||
267 | - | node_index children[16]; | ||
268 | - | } trie_node; | ||
269 | - | |||
270 | - | struct git_oid_shorten { | ||
271 | - | trie_node *nodes; | ||
272 | - | size_t node_count, size; | ||
273 | - | int min_length, full; | ||
274 | - | }; | ||
275 | - | |||
276 | 23 | 2 | static int resize_trie(git_oid_shorten *self, size_t new_size) | |
277 | - | { | ||
278 | 23 | 2 | self->nodes = git__reallocarray(self->nodes, new_size, sizeof(trie_node)); | |
279 | 23 | 3,4 | GIT_ERROR_CHECK_ALLOC(self->nodes); | |
280 | - | |||
281 | 23 | 5 | if (new_size > self->size) { | |
282 | 23 | 6 | memset(&self->nodes[self->size], 0x0, (new_size - self->size) * sizeof(trie_node)); | |
283 | - | } | ||
284 | - | |||
285 | 23 | 7 | self->size = new_size; | |
286 | 23 | 7 | return 0; | |
287 | - | } | ||
288 | - | |||
289 | 34177 | 2 | static trie_node *push_leaf(git_oid_shorten *os, node_index idx, int push_at, const char *oid) | |
290 | - | { | ||
291 | - | trie_node *node, *leaf; | ||
292 | - | node_index idx_leaf; | ||
293 | - | |||
294 | 34177 | 2 | if (os->node_count >= os->size) { | |
295 | 20 | 3,4 | if (resize_trie(os, os->size * 2) < 0) | |
296 | ##### | 5 | return NULL; | |
297 | - | } | ||
298 | - | |||
299 | 34177 | 6 | idx_leaf = (node_index)os->node_count++; | |
300 | - | |||
301 | 34177 | 6 | if (os->node_count == SHRT_MAX) { | |
302 | 1 | 7 | os->full = 1; | |
303 | 1 | 7 | return NULL; | |
304 | - | } | ||
305 | - | |||
306 | 34176 | 8 | node = &os->nodes[idx]; | |
307 | 34176 | 8 | node->children[push_at] = -idx_leaf; | |
308 | - | |||
309 | 34176 | 8 | leaf = &os->nodes[idx_leaf]; | |
310 | 34176 | 8 | leaf->tail = oid; | |
311 | - | |||
312 | 34176 | 8 | return node; | |
313 | - | } | ||
314 | - | |||
315 | 3 | 2 | git_oid_shorten *git_oid_shorten_new(size_t min_length) | |
316 | - | { | ||
317 | - | git_oid_shorten *os; | ||
318 | - | |||
319 | 3 | 2,3 | assert((size_t)((int)min_length) == min_length); | |
320 | - | |||
321 | 3 | 4 | os = git__calloc(1, sizeof(git_oid_shorten)); | |
322 | 3 | 5 | if (os == NULL) | |
323 | ##### | 6 | return NULL; | |
324 | - | |||
325 | 3 | 7,8 | if (resize_trie(os, 16) < 0) { | |
326 | ##### | 9 | git__free(os); | |
327 | ##### | 10 | return NULL; | |
328 | - | } | ||
329 | - | |||
330 | 3 | 11 | os->node_count = 1; | |
331 | 3 | 11 | os->min_length = (int)min_length; | |
332 | - | |||
333 | 3 | 11 | return os; | |
334 | - | } | ||
335 | - | |||
336 | 3 | 2 | void git_oid_shorten_free(git_oid_shorten *os) | |
337 | - | { | ||
338 | 3 | 2 | if (os == NULL) | |
339 | 3 | 3,6 | return; | |
340 | - | |||
341 | 3 | 4 | git__free(os->nodes); | |
342 | 3 | 5 | git__free(os); | |
343 | - | } | ||
344 | - | |||
345 | - | |||
346 | - | /* | ||
347 | - | * What wizardry is this? | ||
348 | - | * | ||
349 | - | * This is just a memory-optimized trie: basically a very fancy | ||
350 | - | * 16-ary tree, which is used to store the prefixes of the OID | ||
351 | - | * strings. | ||
352 | - | * | ||
353 | - | * Read more: http://en.wikipedia.org/wiki/Trie | ||
354 | - | * | ||
355 | - | * Magic that happens in this method: | ||
356 | - | * | ||
357 | - | * - Each node in the trie is an union, so it can work both as | ||
358 | - | * a normal node, or as a leaf. | ||
359 | - | * | ||
360 | - | * - Each normal node points to 16 children (one for each possible | ||
361 | - | * character in the oid). This is *not* stored in an array of | ||
362 | - | * pointers, because in a 64-bit arch this would be sucking | ||
363 | - | * 16*sizeof(void*) = 128 bytes of memory per node, which is | ||
364 | - | * insane. What we do is store Node Indexes, and use these indexes | ||
365 | - | * to look up each node in the om->index array. These indexes are | ||
366 | - | * signed shorts, so this limits the amount of unique OIDs that | ||
367 | - | * fit in the structure to about 20000 (assuming a more or less uniform | ||
368 | - | * distribution). | ||
369 | - | * | ||
370 | - | * - All the nodes in om->index array are stored contiguously in | ||
371 | - | * memory, and each of them is 32 bytes, so we fit 2x nodes per | ||
372 | - | * cache line. Convenient for speed. | ||
373 | - | * | ||
374 | - | * - To differentiate the leafs from the normal nodes, we store all | ||
375 | - | * the indexes towards a leaf as a negative index (indexes to normal | ||
376 | - | * nodes are positives). When we find that one of the children for | ||
377 | - | * a node has a negative value, that means it's going to be a leaf. | ||
378 | - | * This reduces the amount of indexes we have by two, but also reduces | ||
379 | - | * the size of each node by 1-4 bytes (the amount we would need to | ||
380 | - | * add a `is_leaf` field): this is good because it allows the nodes | ||
381 | - | * to fit cleanly in cache lines. | ||
382 | - | * | ||
383 | - | * - Once we reach an empty children, instead of continuing to insert | ||
384 | - | * new nodes for each remaining character of the OID, we store a pointer | ||
385 | - | * to the tail in the leaf; if the leaf is reached again, we turn it | ||
386 | - | * into a normal node and use the tail to create a new leaf. | ||
387 | - | * | ||
388 | - | * This is a pretty good balance between performance and memory usage. | ||
389 | - | */ | ||
390 | 25560 | 2 | int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid) | |
391 | - | { | ||
392 | - | int i; | ||
393 | - | bool is_leaf; | ||
394 | - | node_index idx; | ||
395 | - | |||
396 | 25560 | 2 | if (os->full) { | |
397 | ##### | 3 | git_error_set(GIT_ERROR_INVALID, "unable to shorten OID - OID set full"); | |
398 | ##### | 4 | return -1; | |
399 | - | } | ||
400 | - | |||
401 | 25560 | 5 | if (text_oid == NULL) | |
402 | ##### | 6 | return os->min_length; | |
403 | - | |||
404 | 25560 | 7 | idx = 0; | |
405 | 25560 | 7 | is_leaf = false; | |
406 | - | |||
407 | 101165 | 7,28,29 | for (i = 0; i < GIT_OID_HEXSZ; ++i) { | |
408 | 101164 | 8 | int c = git__fromhex(text_oid[i]); | |
409 | - | trie_node *node; | ||
410 | - | |||
411 | 101164 | 9 | if (c == -1) { | |
412 | ##### | 10 | git_error_set(GIT_ERROR_INVALID, "unable to shorten OID - invalid hex value"); | |
413 | ##### | 11 | return -1; | |
414 | - | } | ||
415 | - | |||
416 | 101164 | 12 | node = &os->nodes[idx]; | |
417 | - | |||
418 | 101164 | 12 | if (is_leaf) { | |
419 | - | const char *tail; | ||
420 | - | |||
421 | 8618 | 13 | tail = node->tail; | |
422 | 8618 | 13 | node->tail = NULL; | |
423 | - | |||
424 | 8618 | 13,14 | node = push_leaf(os, idx, git__fromhex(tail[0]), &tail[1]); | |
425 | 8618 | 15 | if (node == NULL) { | |
426 | ##### | 16 | if (os->full) | |
427 | ##### | 17 | git_error_set(GIT_ERROR_INVALID, "unable to shorten OID - OID set full"); | |
428 | ##### | 18 | return -1; | |
429 | - | } | ||
430 | - | } | ||
431 | - | |||
432 | 101164 | 19 | if (node->children[c] == 0) { | |
433 | 25559 | 20,21 | if (push_leaf(os, idx, c, &text_oid[i + 1]) == NULL) { | |
434 | 1 | 22 | if (os->full) | |
435 | 1 | 23 | git_error_set(GIT_ERROR_INVALID, "unable to shorten OID - OID set full"); | |
436 | 1 | 24 | return -1; | |
437 | - | } | ||
438 | 25558 | 25 | break; | |
439 | - | } | ||
440 | - | |||
441 | 75605 | 26 | idx = node->children[c]; | |
442 | 75605 | 26 | is_leaf = false; | |
443 | - | |||
444 | 75605 | 26 | if (idx < 0) { | |
445 | 8619 | 27 | node->children[c] = idx = -idx; | |
446 | 8619 | 27 | is_leaf = true; | |
447 | - | } | ||
448 | - | } | ||
449 | - | |||
450 | 25559 | 30 | if (++i > os->min_length) | |
451 | 15 | 31 | os->min_length = i; | |
452 | - | |||
453 | 25559 | 32 | return os->min_length; | |
454 | - | } | ||
455 | - |