]> git.ipfire.org Git - thirdparty/git.git/blame - reftable/iter.c
reftable: make reftable_record a tagged union
[thirdparty/git.git] / reftable / iter.c
CommitLineData
46bc0e73
HWN
1/*
2Copyright 2020 Google LLC
3
4Use of this source code is governed by a BSD-style
5license that can be found in the LICENSE file or at
6https://developers.google.com/open-source/licenses/bsd
7*/
8
9#include "iter.h"
10
11#include "system.h"
12
13#include "block.h"
14#include "generic.h"
15#include "constants.h"
16#include "reader.h"
17#include "reftable-error.h"
18
19int iterator_is_null(struct reftable_iterator *it)
20{
21 return !it->ops;
22}
23
24static void filtering_ref_iterator_close(void *iter_arg)
25{
26 struct filtering_ref_iterator *fri = iter_arg;
27 strbuf_release(&fri->oid);
28 reftable_iterator_destroy(&fri->it);
29}
30
31static int filtering_ref_iterator_next(void *iter_arg,
32 struct reftable_record *rec)
33{
34 struct filtering_ref_iterator *fri = iter_arg;
66c0daba 35 struct reftable_ref_record *ref = &rec->u.ref;
46bc0e73
HWN
36 int err = 0;
37 while (1) {
38 err = reftable_iterator_next_ref(&fri->it, ref);
39 if (err != 0) {
40 break;
41 }
42
43 if (fri->double_check) {
44 struct reftable_iterator it = { NULL };
45
46 err = reftable_table_seek_ref(&fri->tab, &it,
47 ref->refname);
48 if (err == 0) {
49 err = reftable_iterator_next_ref(&it, ref);
50 }
51
52 reftable_iterator_destroy(&it);
53
54 if (err < 0) {
55 break;
56 }
57
58 if (err > 0) {
59 continue;
60 }
61 }
62
63 if (ref->value_type == REFTABLE_REF_VAL2 &&
64 (!memcmp(fri->oid.buf, ref->value.val2.target_value,
65 fri->oid.len) ||
66 !memcmp(fri->oid.buf, ref->value.val2.value,
67 fri->oid.len)))
68 return 0;
69
70 if (ref->value_type == REFTABLE_REF_VAL1 &&
71 !memcmp(fri->oid.buf, ref->value.val1, fri->oid.len)) {
72 return 0;
73 }
74 }
75
76 reftable_ref_record_release(ref);
77 return err;
78}
79
80static struct reftable_iterator_vtable filtering_ref_iterator_vtable = {
81 .next = &filtering_ref_iterator_next,
82 .close = &filtering_ref_iterator_close,
83};
84
85void iterator_from_filtering_ref_iterator(struct reftable_iterator *it,
86 struct filtering_ref_iterator *fri)
87{
88 assert(!it->ops);
89 it->iter_arg = fri;
90 it->ops = &filtering_ref_iterator_vtable;
91}
92
93static void indexed_table_ref_iter_close(void *p)
94{
95 struct indexed_table_ref_iter *it = p;
96 block_iter_close(&it->cur);
97 reftable_block_done(&it->block_reader.block);
98 reftable_free(it->offsets);
99 strbuf_release(&it->oid);
100}
101
102static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
103{
104 uint64_t off;
105 int err = 0;
106 if (it->offset_idx == it->offset_len) {
107 it->is_finished = 1;
108 return 1;
109 }
110
111 reftable_block_done(&it->block_reader.block);
112
113 off = it->offsets[it->offset_idx++];
114 err = reader_init_block_reader(it->r, &it->block_reader, off,
115 BLOCK_TYPE_REF);
116 if (err < 0) {
117 return err;
118 }
119 if (err > 0) {
120 /* indexed block does not exist. */
121 return REFTABLE_FORMAT_ERROR;
122 }
123 block_reader_start(&it->block_reader, &it->cur);
124 return 0;
125}
126
127static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
128{
129 struct indexed_table_ref_iter *it = p;
66c0daba 130 struct reftable_ref_record *ref = &rec->u.ref;
46bc0e73
HWN
131
132 while (1) {
133 int err = block_iter_next(&it->cur, rec);
134 if (err < 0) {
135 return err;
136 }
137
138 if (err > 0) {
139 err = indexed_table_ref_iter_next_block(it);
140 if (err < 0) {
141 return err;
142 }
143
144 if (it->is_finished) {
145 return 1;
146 }
147 continue;
148 }
149 /* BUG */
150 if (!memcmp(it->oid.buf, ref->value.val2.target_value,
151 it->oid.len) ||
152 !memcmp(it->oid.buf, ref->value.val2.value, it->oid.len)) {
153 return 0;
154 }
155 }
156}
157
158int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
159 struct reftable_reader *r, uint8_t *oid,
160 int oid_len, uint64_t *offsets, int offset_len)
161{
162 struct indexed_table_ref_iter empty = INDEXED_TABLE_REF_ITER_INIT;
163 struct indexed_table_ref_iter *itr =
164 reftable_calloc(sizeof(struct indexed_table_ref_iter));
165 int err = 0;
166
167 *itr = empty;
168 itr->r = r;
169 strbuf_add(&itr->oid, oid, oid_len);
170
171 itr->offsets = offsets;
172 itr->offset_len = offset_len;
173
174 err = indexed_table_ref_iter_next_block(itr);
175 if (err < 0) {
176 reftable_free(itr);
177 } else {
178 *dest = itr;
179 }
180 return err;
181}
182
183static struct reftable_iterator_vtable indexed_table_ref_iter_vtable = {
184 .next = &indexed_table_ref_iter_next,
185 .close = &indexed_table_ref_iter_close,
186};
187
188void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it,
189 struct indexed_table_ref_iter *itr)
190{
191 assert(!it->ops);
192 it->iter_arg = itr;
193 it->ops = &indexed_table_ref_iter_vtable;
194}