packfile: define and use bsearch_pack()

The method bsearch_hash() generalizes binary searches using a fanout table. The only consumer is currently find_pack_entry_one(). It requires a bit of pointer arithmetic to align the fanout table and the lookup table depending on the pack-index version. Extract the pack-index pointer arithmetic to a new method, bsearch_pack(), so this can be re-used in other code paths. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Mar 22, 2018 at 13:40 UTC 3d475f46a8225a9cc549ac5cb2c51d6ecd9e0f7c
2 files changed +34 -16
packfile.c
+26 -16
@@ -1654,6 +1654,29 @@ out:
1654 return data;
1655 }
1656
1657 +int bsearch_pack(const struct object_id *oid, const struct packed_git *p, uint32_t *result)
1658 +{
1659 + const unsigned char *index_fanout = p->index_data;
1660 + const unsigned char *index_lookup;
1661 + int index_lookup_width;
1662 +
1663 + if (!index_fanout)
1664 + BUG("bsearch_pack called without a valid pack-index");
1665 +
1666 + index_lookup = index_fanout + 4 * 256;
1667 + if (p->index_version == 1) {
1668 + index_lookup_width = 24;
1669 + index_lookup += 4;
1670 + } else {
1671 + index_lookup_width = 20;
1672 + index_fanout += 8;
1673 + index_lookup += 8;
1674 + }
1675 +
1676 + return bsearch_hash(oid->hash, (const uint32_t*)index_fanout,
1677 + index_lookup, index_lookup_width, result);
1678 +}
1679 +
1680 const unsigned char *nth_packed_object_sha1(struct packed_git *p,
1681 uint32_t n)
1682 {
@@ -1720,30 +1743,17 @@ off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n)
1743 off_t find_pack_entry_one(const unsigned char *sha1,
1744 struct packed_git *p)
1745 {
1723 - const uint32_t *level1_ofs = p->index_data;
1746 const unsigned char *index = p->index_data;
1725 - unsigned stride;
1747 + struct object_id oid;
1748 uint32_t result;
1749
1750 if (!index) {
1751 if (open_pack_index(p))
1752 return 0;
1731 - level1_ofs = p->index_data;
1732 - index = p->index_data;
1733 - }
1734 - if (p->index_version > 1) {
1735 - level1_ofs += 2;
1736 - index += 8;
1737 - }
1738 - index += 4 * 256;
1739 - if (p->index_version > 1) {
1740 - stride = 20;
1741 - } else {
1742 - stride = 24;
1743 - index += 4;
1753 }
1754
1746 - if (bsearch_hash(sha1, level1_ofs, index, stride, &result))
1755 + hashcpy(oid.hash, sha1);
1756 + if (bsearch_pack(&oid, p, &result))
1757 return nth_packed_object_offset(p, result);
1758 return 0;
1759 }
packfile.h
+8
@@ -78,6 +78,14 @@ extern struct packed_git *add_packed_git(const char *path, size_t path_len, int
78 */
79 extern void check_pack_index_ptr(const struct packed_git *p, const void *ptr);
80
81 +/*
82 + * Perform binary search on a pack-index for a given oid. Packfile is expected to
83 + * have a valid pack-index.
84 + *
85 + * See 'bsearch_hash' for more information.
86 + */
87 +int bsearch_pack(const struct object_id *oid, const struct packed_git *p, uint32_t *result);
88 +
89 /*
90 * Return the SHA-1 of the nth object within the specified packfile.
91 * Open the index if it is not already open. The return value points