From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Subject: [PATCH v3 2/6] varint-in-pack: refactor varint encoding/decoding
Date: Thu, 1 Dec 2011 16:40:45 -0800 [thread overview]
Message-ID: <1322786449-25753-3-git-send-email-gitster@pobox.com> (raw)
In-Reply-To: <1322786449-25753-1-git-send-email-gitster@pobox.com>
Refactor encode/decode_in_pack_varint() functions from OFS_DELTA codepaths
to read and write variable-length integers in the pack stream.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin/pack-objects.c | 28 +++++++++++++---------------
pack-write.c | 27 +++++++++++++++++++++++++++
pack.h | 2 ++
sha1_file.c | 18 ++++++------------
4 files changed, 48 insertions(+), 27 deletions(-)
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index dde913e..72206a9 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -210,7 +210,7 @@ static unsigned long write_object(struct sha1file *f,
{
unsigned long size, limit, datalen;
void *buf;
- unsigned char header[10], dheader[10];
+ unsigned char header[10];
unsigned hdrlen;
enum object_type type;
int usable_delta, to_reuse;
@@ -304,17 +304,16 @@ static unsigned long write_object(struct sha1file *f,
* base from this object's position in the pack.
*/
off_t ofs = entry->idx.offset - entry->delta->idx.offset;
- unsigned pos = sizeof(dheader) - 1;
- dheader[pos] = ofs & 127;
- while (ofs >>= 7)
- dheader[--pos] = 128 | (--ofs & 127);
- if (limit && hdrlen + sizeof(dheader) - pos + datalen + 20 >= limit) {
+ unsigned char dheader[10];
+ unsigned pos = encode_in_pack_varint(ofs, dheader);
+
+ if (limit && hdrlen + pos + datalen + 20 >= limit) {
free(buf);
return 0;
}
sha1write(f, header, hdrlen);
- sha1write(f, dheader + pos, sizeof(dheader) - pos);
- hdrlen += sizeof(dheader) - pos;
+ sha1write(f, dheader, pos);
+ hdrlen += pos;
} else if (type == OBJ_REF_DELTA) {
/*
* Deltas with a base reference contain
@@ -369,17 +368,16 @@ static unsigned long write_object(struct sha1file *f,
if (type == OBJ_OFS_DELTA) {
off_t ofs = entry->idx.offset - entry->delta->idx.offset;
- unsigned pos = sizeof(dheader) - 1;
- dheader[pos] = ofs & 127;
- while (ofs >>= 7)
- dheader[--pos] = 128 | (--ofs & 127);
- if (limit && hdrlen + sizeof(dheader) - pos + datalen + 20 >= limit) {
+ unsigned char dheader[10];
+ unsigned pos = encode_in_pack_varint(ofs, dheader);
+
+ if (limit && hdrlen + pos + datalen + 20 >= limit) {
unuse_pack(&w_curs);
return 0;
}
sha1write(f, header, hdrlen);
- sha1write(f, dheader + pos, sizeof(dheader) - pos);
- hdrlen += sizeof(dheader) - pos;
+ sha1write(f, dheader, pos);
+ hdrlen += pos;
reused_delta++;
} else if (type == OBJ_REF_DELTA) {
if (limit && hdrlen + 20 + datalen + 20 >= limit) {
diff --git a/pack-write.c b/pack-write.c
index cadc3e1..5702cec 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -302,6 +302,33 @@ char *index_pack_lockfile(int ip_out)
return NULL;
}
+uintmax_t decode_in_pack_varint(const unsigned char **bufp)
+{
+ const unsigned char *buf = *bufp;
+ unsigned char c = *buf++;
+ uintmax_t val = c & 127;
+ while (c & 128) {
+ val += 1;
+ if (!val || MSB(val, 7))
+ return 0; /* overflow */
+ c = *buf++;
+ val = (val << 7) + (c & 127);
+ }
+ *bufp = buf;
+ return val;
+}
+
+int encode_in_pack_varint(uintmax_t value, unsigned char *buf)
+{
+ unsigned char varint[16];
+ unsigned pos = sizeof(varint) - 1;
+ varint[pos] = value & 127;
+ while (value >>= 7)
+ varint[--pos] = 128 | (--value & 127);
+ memcpy(buf, varint + pos, sizeof(varint) - pos);
+ return sizeof(varint) - pos;
+}
+
/*
* The per-object header is a pretty dense thing, which is
* - first byte: low four bits are "size", then three bits of "type",
diff --git a/pack.h b/pack.h
index cfb0f69..d7dc6ca 100644
--- a/pack.h
+++ b/pack.h
@@ -79,6 +79,8 @@ extern off_t write_pack_header(struct sha1file *f, uint32_t);
extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t, unsigned char *, off_t);
extern char *index_pack_lockfile(int fd);
extern int encode_in_pack_object_header(enum object_type, uintmax_t, unsigned char *);
+extern int encode_in_pack_varint(uintmax_t, unsigned char *);
+extern uintmax_t decode_in_pack_varint(const unsigned char **);
#define PH_ERROR_EOF (-1)
#define PH_ERROR_PACK_SIGNATURE (-2)
diff --git a/sha1_file.c b/sha1_file.c
index c96e366..f066c2b 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1484,20 +1484,14 @@ static off_t get_delta_base(struct packed_git *p,
* is stupid, as then a REF_DELTA would be smaller to store.
*/
if (type == OBJ_OFS_DELTA) {
- unsigned used = 0;
- unsigned char c = base_info[used++];
- base_offset = c & 127;
- while (c & 128) {
- base_offset += 1;
- if (!base_offset || MSB(base_offset, 7))
- return 0; /* overflow */
- c = base_info[used++];
- base_offset = (base_offset << 7) + (c & 127);
- }
- base_offset = delta_obj_offset - base_offset;
+ const unsigned char *buf = base_info;
+ uintmax_t ofs = decode_in_pack_varint(&buf);
+ if (!ofs && buf == base_info)
+ return 0; /* overflow */
+ base_offset = delta_obj_offset - ofs;
if (base_offset <= 0 || base_offset >= delta_obj_offset)
return 0; /* out of bound */
- *curpos += used;
+ *curpos += buf - base_info;
} else if (type == OBJ_REF_DELTA) {
/* The base entry _must_ be in the same pack */
base_offset = find_pack_entry_one(base_info, p);
--
1.7.8.rc4.177.g4d64
next prev parent reply other threads:[~2011-12-02 0:41 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-01 0:27 [PATCH v2 0/5] Bulk Check-in Junio C Hamano
2011-12-01 0:27 ` [PATCH v2 1/5] write_pack_header(): a helper function Junio C Hamano
2011-12-01 0:27 ` [PATCH v2 2/5] create_tmp_packfile(): " Junio C Hamano
2011-12-01 0:27 ` [PATCH v2 3/5] finish_tmp_packfile(): " Junio C Hamano
2011-12-01 0:27 ` [PATCH v2 4/5] csum-file: introduce sha1file_checkpoint Junio C Hamano
2011-12-01 0:27 ` [PATCH v2 5/5] bulk-checkin: replace fast-import based implementation Junio C Hamano
2011-12-01 8:05 ` Nguyen Thai Ngoc Duy
2011-12-01 15:46 ` Junio C Hamano
2011-12-02 0:40 ` [PATCH v3 0/6] Bulk check-in Junio C Hamano
2011-12-02 0:40 ` [PATCH v3 1/6] bulk-checkin: replace fast-import based implementation Junio C Hamano
2011-12-02 0:40 ` Junio C Hamano [this message]
2011-12-02 0:40 ` [PATCH v3 3/6] new representation types in the packstream Junio C Hamano
2011-12-02 0:40 ` [PATCH v3 4/6] bulk-checkin: allow the same data to be multiply hashed Junio C Hamano
2011-12-02 0:40 ` [PATCH v3 5/6] bulk-checkin: support chunked-object encoding Junio C Hamano
2011-12-02 0:40 ` [PATCH v3 6/6] chunked-object: fallback checkout codepaths Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1322786449-25753-3-git-send-email-gitster@pobox.com \
--to=gitster@pobox.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).