[PATCH 2/6] Read the base offset or name of delta objects
Signed-off-by: Hervé Cauwelier <herve@itaapy.com>
---
src/cc-compat.h | 3 +++
src/odb.c | 28 ++++++++++++++++++++++++++--
2 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/src/cc-compat.h b/src/cc-compat.h
index 8997caa..8dd6774 100644
--- a/src/cc-compat.h
+++ b/src/cc-compat.h
@@ -30,6 +30,9 @@
# define GIT_TYPEOF(x)
#endif
+#define bitsizeof(x) (CHAR_BIT * sizeof(x))
+#define MSB(x, bits) ((x) & GIT_TYPEOF(x)(~0ULL << (bitsizeof(x) - (bits))))
+
/*
* Does our compiler/platform support the C99 <inttypes.h> and
* <stdint.h> header files. (C99 requires that <inttypes.h>
diff --git a/src/odb.c b/src/odb.c
index a562a19..3cfc932 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -97,8 +97,10 @@ struct git_odb {
};
typedef struct { /* object header data */
- git_otype type; /* object type */
- size_t size; /* object size */
+ git_otype type; /* object type */
+ size_t size; /* object size */
+ off_t base_offset; /* delta base offset (GIT_OBJ_OFS_DELTA) */
+ git_oid base_name; /* delta base name (GIT_OBJ_REF_DELTA) */
} obj_hdr;
static struct {
@@ -238,6 +240,7 @@ static size_t get_binary_object_header(obj_hdr *hdr, gitfo_buf *obj)
unsigned char c;
unsigned char *data = obj->data;
size_t shift, size, used = 0;
+ off_t base_offset;
if (obj->len == 0)
return 0;
@@ -258,6 +261,27 @@ static size_t get_binary_object_header(obj_hdr *hdr, gitfo_buf *obj)
}
hdr->size = size;
+ hdr->base_offset = 0;
+ hdr->base_name.id[0] = '\0';
+
+ if (hdr->type == GIT_OBJ_OFS_DELTA) {
+ c = data[used++];
+ base_offset = c & 127;
+ while (c & 128) {
+ base_offset++;
+ if (!base_offset || MSB(base_offset, 7))
+ return 0; /* overflow */
+ c = data[used++];
+ base_offset = (base_offset << 7) + (c & 127);
+ }
+ assert(base_offset > 0);
+ hdr->base_offset = base_offset;
+ }
+ else if (hdr->type == GIT_OBJ_REF_DELTA) {
+ git_oid_mkraw(&hdr->base_name, data + used);
+ used += 20;
+ }
+
return used;
}
--
1.6.4.4