t/t9*: avoid redundant uses of cat
[git.git] / reftable / iter.c
blob7aa30c4a51e54ec5442b9d8a3bf90b8119c5a4f0
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 static void filtering_ref_iterator_close(void *iter_arg)
21 struct filtering_ref_iterator *fri = iter_arg;
22 strbuf_release(&fri->oid);
23 reftable_iterator_destroy(&fri->it);
26 static int filtering_ref_iterator_next(void *iter_arg,
27 struct reftable_record *rec)
29 struct filtering_ref_iterator *fri = iter_arg;
30 struct reftable_ref_record *ref = &rec->u.ref;
31 int err = 0;
32 while (1) {
33 err = reftable_iterator_next_ref(&fri->it, ref);
34 if (err != 0) {
35 break;
38 if (fri->double_check) {
39 struct reftable_iterator it = { NULL };
41 err = reftable_table_seek_ref(&fri->tab, &it,
42 ref->refname);
43 if (err == 0) {
44 err = reftable_iterator_next_ref(&it, ref);
47 reftable_iterator_destroy(&it);
49 if (err < 0) {
50 break;
53 if (err > 0) {
54 continue;
58 if (ref->value_type == REFTABLE_REF_VAL2 &&
59 (!memcmp(fri->oid.buf, ref->value.val2.target_value,
60 fri->oid.len) ||
61 !memcmp(fri->oid.buf, ref->value.val2.value,
62 fri->oid.len)))
63 return 0;
65 if (ref->value_type == REFTABLE_REF_VAL1 &&
66 !memcmp(fri->oid.buf, ref->value.val1, fri->oid.len)) {
67 return 0;
71 reftable_ref_record_release(ref);
72 return err;
75 static struct reftable_iterator_vtable filtering_ref_iterator_vtable = {
76 .next = &filtering_ref_iterator_next,
77 .close = &filtering_ref_iterator_close,
80 void iterator_from_filtering_ref_iterator(struct reftable_iterator *it,
81 struct filtering_ref_iterator *fri)
83 assert(!it->ops);
84 it->iter_arg = fri;
85 it->ops = &filtering_ref_iterator_vtable;
88 static void indexed_table_ref_iter_close(void *p)
90 struct indexed_table_ref_iter *it = p;
91 block_iter_close(&it->cur);
92 reftable_block_done(&it->block_reader.block);
93 reftable_free(it->offsets);
94 strbuf_release(&it->oid);
97 static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
99 uint64_t off;
100 int err = 0;
101 if (it->offset_idx == it->offset_len) {
102 it->is_finished = 1;
103 return 1;
106 reftable_block_done(&it->block_reader.block);
108 off = it->offsets[it->offset_idx++];
109 err = reader_init_block_reader(it->r, &it->block_reader, off,
110 BLOCK_TYPE_REF);
111 if (err < 0) {
112 return err;
114 if (err > 0) {
115 /* indexed block does not exist. */
116 return REFTABLE_FORMAT_ERROR;
118 block_reader_start(&it->block_reader, &it->cur);
119 return 0;
122 static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
124 struct indexed_table_ref_iter *it = p;
125 struct reftable_ref_record *ref = &rec->u.ref;
127 while (1) {
128 int err = block_iter_next(&it->cur, rec);
129 if (err < 0) {
130 return err;
133 if (err > 0) {
134 err = indexed_table_ref_iter_next_block(it);
135 if (err < 0) {
136 return err;
139 if (it->is_finished) {
140 return 1;
142 continue;
144 /* BUG */
145 if (!memcmp(it->oid.buf, ref->value.val2.target_value,
146 it->oid.len) ||
147 !memcmp(it->oid.buf, ref->value.val2.value, it->oid.len)) {
148 return 0;
153 int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
154 struct reftable_reader *r, uint8_t *oid,
155 int oid_len, uint64_t *offsets, int offset_len)
157 struct indexed_table_ref_iter empty = INDEXED_TABLE_REF_ITER_INIT;
158 struct indexed_table_ref_iter *itr = reftable_calloc(1, sizeof(*itr));
159 int err = 0;
161 *itr = empty;
162 itr->r = r;
163 strbuf_add(&itr->oid, oid, oid_len);
165 itr->offsets = offsets;
166 itr->offset_len = offset_len;
168 err = indexed_table_ref_iter_next_block(itr);
169 if (err < 0) {
170 reftable_free(itr);
171 } else {
172 *dest = itr;
174 return err;
177 static struct reftable_iterator_vtable indexed_table_ref_iter_vtable = {
178 .next = &indexed_table_ref_iter_next,
179 .close = &indexed_table_ref_iter_close,
182 void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it,
183 struct indexed_table_ref_iter *itr)
185 assert(!it->ops);
186 it->iter_arg = itr;
187 it->ops = &indexed_table_ref_iter_vtable;