551 * |
551 * |
552 * -4: match is ambiguous (multiple candidates) |
552 * -4: match is ambiguous (multiple candidates) |
553 * -2: not found |
553 * -2: not found |
554 * rest: valid rev |
554 * rest: valid rev |
555 */ |
555 */ |
556 static int nt_find(indexObject *self, const char *node, Py_ssize_t nodelen) |
556 static int nt_find(indexObject *self, const char *node, Py_ssize_t nodelen, |
557 { |
557 int hex) |
|
558 { |
|
559 int (*getnybble)(const char *, Py_ssize_t) = hex ? hexdigit : nt_level; |
558 int level, maxlevel, off; |
560 int level, maxlevel, off; |
559 |
561 |
560 if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0) |
562 if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0) |
561 return -1; |
563 return -1; |
562 |
564 |
563 if (self->nt == NULL) |
565 if (self->nt == NULL) |
564 return -2; |
566 return -2; |
565 |
567 |
566 maxlevel = nodelen > 20 ? 40 : ((int)nodelen * 2); |
568 if (hex) |
|
569 maxlevel = nodelen > 40 ? 40 : nodelen; |
|
570 else |
|
571 maxlevel = nodelen > 20 ? 40 : ((int)nodelen * 2); |
567 |
572 |
568 for (level = off = 0; level < maxlevel; level++) { |
573 for (level = off = 0; level < maxlevel; level++) { |
569 int k = nt_level(node, level); |
574 int k = getnybble(node, level); |
570 nodetree *n = &self->nt[off]; |
575 nodetree *n = &self->nt[off]; |
571 int v = n->children[k]; |
576 int v = n->children[k]; |
572 |
577 |
573 if (v < 0) { |
578 if (v < 0) { |
574 const char *n; |
579 const char *n; |
|
580 Py_ssize_t i; |
|
581 |
575 v = -v - 1; |
582 v = -v - 1; |
576 n = index_node(self, v); |
583 n = index_node(self, v); |
577 if (n == NULL) |
584 if (n == NULL) |
578 return -2; |
585 return -2; |
579 return memcmp(node, n, nodelen > 20 ? 20 : nodelen) |
586 for (i = level; i < maxlevel; i++) |
580 ? -2 : v; |
587 if (getnybble(node, i) != nt_level(n, i)) |
|
588 return -2; |
|
589 return v; |
581 } |
590 } |
582 if (v == 0) |
591 if (v == 0) |
583 return -2; |
592 return -2; |
584 off = v; |
593 off = v; |
585 } |
594 } |