Merge branch 'jc/diff-tree-stdin-fix' into maint
[alt-git.git] / reftable / iter.c
bloba8d174c040658edda3d2c45a9df2f692aef41c9d
1 /*
2 Copyright 2020 Google LLC
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file or at
6 https://developers.google.com/open-source/licenses/bsd
7 */
9 #include "iter.h"
11 #include "system.h"
13 #include "block.h"
14 #include "generic.h"
15 #include "constants.h"
16 #include "reader.h"
17 #include "reftable-error.h"
19 int iterator_is_null(struct reftable_iterator *it)
21 return !it->ops;
24 static void filtering_ref_iterator_close(void *iter_arg)
26 struct filtering_ref_iterator *fri = iter_arg;
27 strbuf_release(&fri->oid);
28 reftable_iterator_destroy(&fri->it);
31 static int filtering_ref_iterator_next(void *iter_arg,
32 struct reftable_record *rec)
34 struct filtering_ref_iterator *fri = iter_arg;
35 struct reftable_ref_record *ref = &rec->u.ref;
36 int err = 0;
37 while (1) {
38 err = reftable_iterator_next_ref(&fri->it, ref);
39 if (err != 0) {
40 break;
43 if (fri->double_check) {
44 struct reftable_iterator it = { NULL };
46 err = reftable_table_seek_ref(&fri->tab, &it,
47 ref->refname);
48 if (err == 0) {
49 err = reftable_iterator_next_ref(&it, ref);
52 reftable_iterator_destroy(&it);
54 if (err < 0) {
55 break;
58 if (err > 0) {
59 continue;
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;
70 if (ref->value_type == REFTABLE_REF_VAL1 &&
71 !memcmp(fri->oid.buf, ref->value.val1, fri->oid.len)) {
72 return 0;
76 reftable_ref_record_release(ref);
77 return err;
80 static struct reftable_iterator_vtable filtering_ref_iterator_vtable = {
81 .next = &filtering_ref_iterator_next,
82 .close = &filtering_ref_iterator_close,
85 void iterator_from_filtering_ref_iterator(struct reftable_iterator *it,
86 struct filtering_ref_iterator *fri)
88 assert(!it->ops);
89 it->iter_arg = fri;
90 it->ops = &filtering_ref_iterator_vtable;
93 static void indexed_table_ref_iter_close(void *p)
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);
102 static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
104 uint64_t off;
105 int err = 0;
106 if (it->offset_idx == it->offset_len) {
107 it->is_finished = 1;
108 return 1;
111 reftable_block_done(&it->block_reader.block);
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;
119 if (err > 0) {
120 /* indexed block does not exist. */
121 return REFTABLE_FORMAT_ERROR;
123 block_reader_start(&it->block_reader, &it->cur);
124 return 0;
127 static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
129 struct indexed_table_ref_iter *it = p;
130 struct reftable_ref_record *ref = &rec->u.ref;
132 while (1) {
133 int err = block_iter_next(&it->cur, rec);
134 if (err < 0) {
135 return err;
138 if (err > 0) {
139 err = indexed_table_ref_iter_next_block(it);
140 if (err < 0) {
141 return err;
144 if (it->is_finished) {
145 return 1;
147 continue;
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;
158 int 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)
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;
167 *itr = empty;
168 itr->r = r;
169 strbuf_add(&itr->oid, oid, oid_len);
171 itr->offsets = offsets;
172 itr->offset_len = offset_len;
174 err = indexed_table_ref_iter_next_block(itr);
175 if (err < 0) {
176 reftable_free(itr);
177 } else {
178 *dest = itr;
180 return err;
183 static struct reftable_iterator_vtable indexed_table_ref_iter_vtable = {
184 .next = &indexed_table_ref_iter_next,
185 .close = &indexed_table_ref_iter_close,
188 void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it,
189 struct indexed_table_ref_iter *itr)
191 assert(!it->ops);
192 it->iter_arg = itr;
193 it->ops = &indexed_table_ref_iter_vtable;