The MIDX file stores pack offset information for a list of objects. The
nth_midxed_object_* methods provide ways to extract this information.

Signed-off-by: Derrick Stolee <dsto...@microsoft.com>
---
 midx.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 midx.h | 15 +++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/midx.c b/midx.c
index c631be451f..4e0df0285a 100644
--- a/midx.c
+++ b/midx.c
@@ -202,6 +202,61 @@ struct pack_midx_details_internal {
        uint32_t internal_offset;
 };
 
+struct pack_midx_details *nth_midxed_object_details(struct midxed_git *m,
+                                                   uint32_t n,
+                                                   struct pack_midx_details *d)
+{
+       struct pack_midx_details_internal *d_internal;
+       const unsigned char *details = m->chunk_object_offsets;
+
+       if (n >= m->num_objects)
+               return NULL;
+
+       d_internal = (struct pack_midx_details_internal*)(details + 8 * n);
+       d->pack_int_id = ntohl(d_internal->pack_int_id);
+       d->offset = ntohl(d_internal->internal_offset);
+
+       if (m->chunk_large_offsets && d->offset & MIDX_LARGE_OFFSET_NEEDED) {
+               uint32_t large_offset = d->offset ^ MIDX_LARGE_OFFSET_NEEDED;
+               const unsigned char *large_offsets = m->chunk_large_offsets + 8 
* large_offset;
+
+               d->offset =  (((uint64_t)ntohl(*((uint32_t *)(large_offsets + 
0)))) << 32) |
+                                        ntohl(*((uint32_t *)(large_offsets + 
4)));
+       }
+
+       return d;
+}
+
+struct pack_midx_entry *nth_midxed_object_entry(struct midxed_git *m,
+                                               uint32_t n,
+                                               struct pack_midx_entry *e)
+{
+       struct pack_midx_details details;
+       const unsigned char *index = m->chunk_oid_lookup;
+
+       if (!nth_midxed_object_details(m, n, &details))
+               return NULL;
+
+       memcpy(e->oid.hash, index + m->hdr->hash_len * n, m->hdr->hash_len);
+       e->pack_int_id = details.pack_int_id;
+       e->offset = details.offset;
+
+       return e;
+}
+
+const struct object_id *nth_midxed_object_oid(struct object_id *oid,
+                                             struct midxed_git *m,
+                                             uint32_t n)
+{
+       struct pack_midx_entry e;
+
+       if (!nth_midxed_object_entry(m, n, &e))
+               return 0;
+
+       hashcpy(oid->hash, e.oid.hash);
+       return oid;
+}
+
 static int midx_sha1_compare(const void *_a, const void *_b)
 {
        struct pack_midx_entry *a = *(struct pack_midx_entry **)_a;
diff --git a/midx.h b/midx.h
index 92b74e49db..9255909ae8 100644
--- a/midx.h
+++ b/midx.h
@@ -85,6 +85,21 @@ struct midxed_git {
 
 extern struct midxed_git *get_midxed_git(const char *pack_dir, struct 
object_id *oid);
 
+struct pack_midx_details {
+       uint32_t pack_int_id;
+       off_t offset;
+};
+
+extern struct pack_midx_details *nth_midxed_object_details(struct midxed_git 
*m,
+                                                          uint32_t n,
+                                                          struct 
pack_midx_details *d);
+extern struct pack_midx_entry *nth_midxed_object_entry(struct midxed_git *m,
+                                                      uint32_t n,
+                                                      struct pack_midx_entry 
*e);
+extern const struct object_id *nth_midxed_object_oid(struct object_id *oid,
+                                                    struct midxed_git *m,
+                                                    uint32_t n);
+
 /*
  * Write a single MIDX file storing the given entries for the
  * given list of packfiles. If midx_name is null, then a temp
-- 
2.15.0

Reply via email to