]> git.ipfire.org Git - thirdparty/git.git/blame - chunk-format.c
midx: use chunk-format API in write_midx_internal()
[thirdparty/git.git] / chunk-format.c
CommitLineData
570df426
DS
1#include "cache.h"
2#include "chunk-format.h"
3#include "csum-file.h"
4
5/*
6 * When writing a chunk-based file format, collect the chunks in
7 * an array of chunk_info structs. The size stores the _expected_
8 * amount of data that will be written by write_fn.
9 */
10struct chunk_info {
11 uint32_t id;
12 uint64_t size;
13 chunk_write_fn write_fn;
14};
15
16struct chunkfile {
17 struct hashfile *f;
18
19 struct chunk_info *chunks;
20 size_t chunks_nr;
21 size_t chunks_alloc;
22};
23
24struct chunkfile *init_chunkfile(struct hashfile *f)
25{
26 struct chunkfile *cf = xcalloc(1, sizeof(*cf));
27 cf->f = f;
28 return cf;
29}
30
31void free_chunkfile(struct chunkfile *cf)
32{
33 if (!cf)
34 return;
35 free(cf->chunks);
36 free(cf);
37}
38
39int get_num_chunks(struct chunkfile *cf)
40{
41 return cf->chunks_nr;
42}
43
44void add_chunk(struct chunkfile *cf,
45 uint32_t id,
46 size_t size,
47 chunk_write_fn fn)
48{
49 ALLOC_GROW(cf->chunks, cf->chunks_nr + 1, cf->chunks_alloc);
50
51 cf->chunks[cf->chunks_nr].id = id;
52 cf->chunks[cf->chunks_nr].write_fn = fn;
53 cf->chunks[cf->chunks_nr].size = size;
54 cf->chunks_nr++;
55}
56
57int write_chunkfile(struct chunkfile *cf, void *data)
58{
59 int i;
60 uint64_t cur_offset = hashfile_total(cf->f);
61
62 /* Add the table of contents to the current offset */
63 cur_offset += (cf->chunks_nr + 1) * CHUNK_TOC_ENTRY_SIZE;
64
65 for (i = 0; i < cf->chunks_nr; i++) {
66 hashwrite_be32(cf->f, cf->chunks[i].id);
67 hashwrite_be64(cf->f, cur_offset);
68
69 cur_offset += cf->chunks[i].size;
70 }
71
72 /* Trailing entry marks the end of the chunks */
73 hashwrite_be32(cf->f, 0);
74 hashwrite_be64(cf->f, cur_offset);
75
76 for (i = 0; i < cf->chunks_nr; i++) {
77 off_t start_offset = hashfile_total(cf->f);
78 int result = cf->chunks[i].write_fn(cf->f, data);
79
80 if (result)
81 return result;
82
83 if (hashfile_total(cf->f) - start_offset != cf->chunks[i].size)
84 BUG("expected to write %"PRId64" bytes to chunk %"PRIx32", but wrote %"PRId64" instead",
85 cf->chunks[i].size, cf->chunks[i].id,
86 hashfile_total(cf->f) - start_offset);
87 }
88
89 return 0;
90}