Signed-off-by: Nicolas Pitre <n...@fluxnic.net>
---
 packv4-parse.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/packv4-parse.c b/packv4-parse.c
index 299fc48..26894bc 100644
--- a/packv4-parse.c
+++ b/packv4-parse.c
@@ -28,3 +28,80 @@ const unsigned char *get_sha1ref(struct packed_git *p,
 
        return sha1;
 }
+
+struct packv4_dict {
+       const unsigned char *data;
+       unsigned int nb_entries;
+       unsigned int offsets[FLEX_ARRAY];
+};
+
+static struct packv4_dict *load_dict(struct packed_git *p, off_t *offset)
+{
+       struct pack_window *w_curs = NULL;
+       off_t curpos = *offset;
+       unsigned long dict_size, avail;
+       unsigned char *src, *data;
+       const unsigned char *cp;
+       git_zstream stream;
+       struct packv4_dict *dict;
+       int nb_entries, i, st;
+
+       /* get uncompressed dictionary data size */
+       src = use_pack(p, &w_curs, curpos, &avail);
+       cp = src;
+       dict_size = decode_varint(&cp);
+       if (dict_size < 3) {
+               error("bad dict size");
+               return NULL;
+       }
+       curpos += cp - src;
+
+       data = xmallocz(dict_size);
+       memset(&stream, 0, sizeof(stream));
+       stream.next_out = data;
+       stream.avail_out = dict_size + 1;
+
+       git_inflate_init(&stream);
+       do {
+               src = use_pack(p, &w_curs, curpos, &stream.avail_in);
+               stream.next_in = src;
+               st = git_inflate(&stream, Z_FINISH);
+               curpos += stream.next_in - src;
+       } while ((st == Z_OK || st == Z_BUF_ERROR) && stream.avail_out);
+       git_inflate_end(&stream);
+       unuse_pack(&w_curs);
+       if (st != Z_STREAM_END || stream.total_out != dict_size) {
+               error("pack dictionary bad");
+               free(data);
+               return NULL;
+       }
+
+       /* count number of entries */
+       nb_entries = 0;
+       cp = data;
+       while (cp < data + dict_size - 3) {
+               cp += 2;  /* prefix bytes */
+               cp += strlen((const char *)cp);  /* entry string */
+               cp += 1;  /* terminating NUL */
+               nb_entries++;
+       }
+       if (cp - data != dict_size) {
+               error("dict size mismatch");
+               free(data);
+               return NULL;
+       }
+
+       dict = xmalloc(sizeof(*dict) + nb_entries * sizeof(dict->offsets[0]));
+       dict->data = data;
+       dict->nb_entries = nb_entries;
+
+       cp = data;
+       for (i = 0; i < nb_entries; i++) {
+               dict->offsets[i] = cp - data;
+               cp += 2;
+               cp += strlen((const char *)cp) + 1;
+       }
+
+       *offset = curpos;
+       return dict;
+}
-- 
1.8.4.38.g317e65b

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to