| 1 | /* |
| 2 | * This Source Code Form is subject to the terms of the Mozilla Public |
| 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 5 | * |
| 6 | * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V. |
| 7 | */ |
| 8 | |
| 9 | #ifndef _GDK_CAND_H_ |
| 10 | #define _GDK_CAND_H_ |
| 11 | |
| 12 | struct canditer { |
| 13 | const oid *oids; /* candidate or exceptions for non-dense */ |
| 14 | BAT *s; /* candidate BAT the iterator is based on */ |
| 15 | oid seq; /* first candidate */ |
| 16 | oid add; /* value to add because of exceptions seen */ |
| 17 | BUN noids; /* number of values in .oids */ |
| 18 | BUN ncand; /* number of candidates */ |
| 19 | BUN next; /* next BUN to return value for */ |
| 20 | BUN offset; /* how much of candidate list BAT we skipped */ |
| 21 | enum { |
| 22 | cand_dense, /* simple dense BAT, i.e. no look ups */ |
| 23 | cand_materialized, /* simple materialized OID list */ |
| 24 | cand_except, /* list of exceptions in vheap */ |
| 25 | } tpe; |
| 26 | }; |
| 27 | |
| 28 | static inline oid |
| 29 | canditer_next(struct canditer *ci) |
| 30 | { |
| 31 | if (ci->next == ci->ncand) |
| 32 | return oid_nil; |
| 33 | switch (ci->tpe) { |
| 34 | case cand_dense: |
| 35 | return ci->seq + ci->next++; |
| 36 | case cand_materialized: |
| 37 | assert(ci->next < ci->noids); |
| 38 | return ci->oids[ci->next++]; |
| 39 | case cand_except: |
| 40 | /* work around compiler error: control reaches end of |
| 41 | * non-void function */ |
| 42 | break; |
| 43 | } |
| 44 | oid o = ci->seq + ci->add + ci->next++; |
| 45 | while (ci->add < ci->noids && o == ci->oids[ci->add]) { |
| 46 | ci->add++; |
| 47 | o++; |
| 48 | } |
| 49 | return o; |
| 50 | } |
| 51 | #define canditer_next_dense(ci) ((ci)->next == (ci)->ncand ? oid_nil : (ci)->seq + (ci)->next++) |
| 52 | #define canditer_next_mater(ci) ((ci)->next == (ci)->ncand ? oid_nil : (ci)->oids[(ci)->next++]) |
| 53 | static inline oid |
| 54 | canditer_next_except(struct canditer *ci) |
| 55 | { |
| 56 | if (ci->next == ci->ncand) |
| 57 | return oid_nil; |
| 58 | oid o = ci->seq + ci->add + ci->next++; |
| 59 | while (ci->add < ci->noids && o == ci->oids[ci->add]) { |
| 60 | ci->add++; |
| 61 | o++; |
| 62 | } |
| 63 | return o; |
| 64 | } |
| 65 | #define canditer_search_dense(ci, o, next) ((o) < (ci)->seq ? next ? 0 : BUN_NONE : (o) >= (ci)->seq + (ci)->ncand ? next ? (ci)->ncand : BUN_NONE : (o) - (ci)->seq) |
| 66 | |
| 67 | |
| 68 | gdk_export BUN canditer_init(struct canditer *ci, BAT *b, BAT *s); |
| 69 | gdk_export oid canditer_peek(struct canditer *ci); |
| 70 | gdk_export oid canditer_last(struct canditer *ci); |
| 71 | gdk_export oid canditer_prev(struct canditer *ci); |
| 72 | gdk_export oid canditer_peekprev(struct canditer *ci); |
| 73 | gdk_export oid canditer_idx(struct canditer *ci, BUN p); |
| 74 | gdk_export void canditer_setidx(struct canditer *ci, BUN p); |
| 75 | gdk_export void canditer_reset(struct canditer *ci); |
| 76 | gdk_export BUN canditer_search(struct canditer *ci, oid o, bool next); |
| 77 | gdk_export BAT *canditer_slice(struct canditer *ci, BUN lo, BUN hi); |
| 78 | gdk_export BAT *canditer_slice2(struct canditer *ci, BUN lo1, BUN hi1, BUN lo2, BUN hi2); |
| 79 | gdk_export gdk_return BATnegcands( BAT *cands, BAT *odels); |
| 80 | |
| 81 | #endif /* _GDK_CAND_H_ */ |
| 82 | |