Skip to content

Commit

Permalink
consolidate two copies of new style object header parsing code.
Browse files Browse the repository at this point in the history
Also while we are at it, remove redundant typename[] array from
unpack_sha1_header.  The only reason it is different from the
type_names[] array in object.c module is that this code cares
about the subset of object types that are valid in a loose
object, so prepare a separate array of boolean that tells us
which types are valid, and share the name translation with the
others.

Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Junio C Hamano committed Sep 1, 2006
1 parent 501524e commit ad1ed5e
Showing 1 changed file with 45 additions and 40 deletions.
85 changes: 45 additions & 40 deletions sha1_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -711,17 +711,39 @@ int legacy_loose_object(unsigned char *map)
return 0;
}

static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz)
static unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep)
{
unsigned shift;
unsigned char c;
unsigned int bits;
unsigned long size;
static const char *typename[8] = {
NULL, /* OBJ_EXT */
"commit", "tree", "blob", "tag",
NULL, NULL, NULL
unsigned long used = 0;

c = buf[used++];
*type = (c >> 4) & 7;
size = c & 15;
shift = 4;
while (c & 0x80) {
if (len <= used)
return 0;
if (sizeof(long) * 8 <= shift)
return 0;
c = buf[used++];
size += (c & 0x7f) << shift;
shift += 7;
}
*sizep = size;
return used;
}

static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz)
{
unsigned long size, used;
static const char valid_loose_object_type[8] = {
0, /* OBJ_EXT */
1, 1, 1, 1, /* "commit", "tree", "blob", "tag" */
0, /* "delta" and others are invalid in a loose object */
};
const char *type;
enum object_type type;

/* Get the data stream */
memset(stream, 0, sizeof(*stream));
Expand All @@ -735,30 +757,20 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
return inflate(stream, 0);
}

c = *map++;
mapsize--;
type = typename[(c >> 4) & 7];
if (!type)
used = unpack_object_header_gently(map, mapsize, &type, &size);
if (!used || !valid_loose_object_type[type])
return -1;

bits = 4;
size = c & 0xf;
while ((c & 0x80)) {
if (bits >= 8*sizeof(long))
return -1;
c = *map++;
size += (c & 0x7f) << bits;
bits += 7;
mapsize--;
}
map += used;
mapsize -= used;

/* Set up the stream for the rest.. */
stream->next_in = map;
stream->avail_in = mapsize;
inflateInit(stream);

/* And generate the fake traditional header */
stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu", type, size);
stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu",
type_names[type], size);
return 0;
}

Expand Down Expand Up @@ -916,25 +928,18 @@ static int packed_delta_info(unsigned char *base_sha1,
static unsigned long unpack_object_header(struct packed_git *p, unsigned long offset,
enum object_type *type, unsigned long *sizep)
{
unsigned shift;
unsigned char c;
unsigned long size;
unsigned long used;

if (offset >= p->pack_size)
if (p->pack_size <= offset)
die("object offset outside of pack file");
c = *((unsigned char *)p->pack_base + offset++);
*type = (c >> 4) & 7;
size = c & 15;
shift = 4;
while (c & 0x80) {
if (offset >= p->pack_size)
die("object offset outside of pack file");
c = *((unsigned char *)p->pack_base + offset++);
size += (c & 0x7f) << shift;
shift += 7;
}
*sizep = size;
return offset;

used = unpack_object_header_gently((unsigned char *)p->pack_base +
offset,
p->pack_size - offset, type, sizep);
if (!used)
die("object offset outside of pack file");

return offset + used;
}

int check_reuse_pack_delta(struct packed_git *p, unsigned long offset,
Expand Down

0 comments on commit ad1ed5e

Please sign in to comment.