]> granicus.if.org Git - postgresql/blob - src/include/utils/arrayaccess.h
Update copyright for 2016
[postgresql] / src / include / utils / arrayaccess.h
1 /*-------------------------------------------------------------------------
2  *
3  * arrayaccess.h
4  *        Declarations for element-by-element access to Postgres arrays.
5  *
6  *
7  * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  * src/include/utils/arrayaccess.h
11  *
12  *-------------------------------------------------------------------------
13  */
14 #ifndef ARRAYACCESS_H
15 #define ARRAYACCESS_H
16
17 #include "access/tupmacs.h"
18 #include "utils/array.h"
19
20
21 /*
22  * Functions for iterating through elements of a flat or expanded array.
23  * These require a state struct "array_iter iter".
24  *
25  * Use "array_iter_setup(&iter, arrayptr);" to prepare to iterate, and
26  * "datumvar = array_iter_next(&iter, &isnullvar, index, ...);" to fetch
27  * the next element into datumvar/isnullvar.
28  * "index" must be the zero-origin element number; we make caller provide
29  * this since caller is generally counting the elements anyway.  Despite
30  * that, these functions can only fetch elements sequentially.
31  */
32
33 typedef struct array_iter
34 {
35         /* datumptr being NULL or not tells if we have flat or expanded array */
36
37         /* Fields used when we have an expanded array */
38         Datum      *datumptr;           /* Pointer to Datum array */
39         bool       *isnullptr;          /* Pointer to isnull array */
40
41         /* Fields used when we have a flat array */
42         char       *dataptr;            /* Current spot in the data area */
43         bits8      *bitmapptr;          /* Current byte of the nulls bitmap, or NULL */
44         int                     bitmask;                /* mask for current bit in nulls bitmap */
45 } array_iter;
46
47
48 static inline void
49 array_iter_setup(array_iter *it, AnyArrayType *a)
50 {
51         if (VARATT_IS_EXPANDED_HEADER(a))
52         {
53                 if (a->xpn.dvalues)
54                 {
55                         it->datumptr = a->xpn.dvalues;
56                         it->isnullptr = a->xpn.dnulls;
57                         /* we must fill all fields to prevent compiler warnings */
58                         it->dataptr = NULL;
59                         it->bitmapptr = NULL;
60                 }
61                 else
62                 {
63                         /* Work with flat array embedded in the expanded datum */
64                         it->datumptr = NULL;
65                         it->isnullptr = NULL;
66                         it->dataptr = ARR_DATA_PTR(a->xpn.fvalue);
67                         it->bitmapptr = ARR_NULLBITMAP(a->xpn.fvalue);
68                 }
69         }
70         else
71         {
72                 it->datumptr = NULL;
73                 it->isnullptr = NULL;
74                 it->dataptr = ARR_DATA_PTR(&a->flt);
75                 it->bitmapptr = ARR_NULLBITMAP(&a->flt);
76         }
77         it->bitmask = 1;
78 }
79
80 static inline Datum
81 array_iter_next(array_iter *it, bool *isnull, int i,
82                                 int elmlen, bool elmbyval, char elmalign)
83 {
84         Datum           ret;
85
86         if (it->datumptr)
87         {
88                 ret = it->datumptr[i];
89                 *isnull = it->isnullptr ? it->isnullptr[i] : false;
90         }
91         else
92         {
93                 if (it->bitmapptr && (*(it->bitmapptr) & it->bitmask) == 0)
94                 {
95                         *isnull = true;
96                         ret = (Datum) 0;
97                 }
98                 else
99                 {
100                         *isnull = false;
101                         ret = fetch_att(it->dataptr, elmbyval, elmlen);
102                         it->dataptr = att_addlength_pointer(it->dataptr, elmlen,
103                                                                                                 it->dataptr);
104                         it->dataptr = (char *) att_align_nominal(it->dataptr, elmalign);
105                 }
106                 it->bitmask <<= 1;
107                 if (it->bitmask == 0x100)
108                 {
109                         if (it->bitmapptr)
110                                 it->bitmapptr++;
111                         it->bitmask = 1;
112                 }
113         }
114
115         return ret;
116 }
117
118 #endif   /* ARRAYACCESS_H */