Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : /*
14 : * @a Martin L. Kersten & Peter Boncz
15 : * @v 2.0
16 : * @+ Value representation
17 : *
18 : *
19 : * When manipulating values, MonetDB puts them into value records.
20 : * The built-in types have a direct entry in the union. Others should
21 : * be represented as a pointer of memory in pval or as a string, which
22 : * is basically the same. In such cases the len field indicates the
23 : * size of this piece of memory.
24 : *
25 : * MonetDB extenders will use value records for passing parameters to
26 : * their new operators. MonetDB algebraic commands receive an (argc,
27 : * argv) combination, where argc is an integer indicating the size of
28 : * the the argv array of value records. On call, the first record,
29 : * argv[0], is always empty. The routine must place its return value -
30 : * if any - there. The other values are the parameters.
31 : *
32 : * Actually, the gdk value type defined here should become a built-in
33 : * type in the kernel. Next step will be to define the corresponding
34 : * extension module.
35 : *
36 : * @+ Value operations
37 : * The following primitives are required to manipulate value records.
38 : * Note that binding a BAT requires upgrading its reference count.
39 : * The receiver of the value should have been cleared or represent
40 : * free space.
41 : */
42 : #include "monetdb_config.h"
43 : #include "gdk.h"
44 : #include "gdk_private.h"
45 :
46 : /* Set V to the type/value combination in T/P. Also see VALinit. In
47 : * this version, if P refers to an external type, no new memory is
48 : * allocated, but instead the pointer P is given to V. */
49 : ValPtr
50 5226730 : VALset(ValPtr v, int t, ptr p)
51 : {
52 5226730 : switch (ATOMstorage(v->vtype = t)) {
53 107471 : case TYPE_void:
54 107471 : v->val.oval = *(oid *) p;
55 107471 : break;
56 0 : case TYPE_msk:
57 0 : v->val.mval = *(msk *) p;
58 0 : break;
59 18105 : case TYPE_bte:
60 18105 : v->val.btval = *(bte *) p;
61 18105 : break;
62 8089 : case TYPE_sht:
63 8089 : v->val.shval = *(sht *) p;
64 8089 : break;
65 229473 : case TYPE_int:
66 229473 : v->val.ival = *(int *) p;
67 229473 : break;
68 2762 : case TYPE_flt:
69 2762 : v->val.fval = *(flt *) p;
70 2762 : break;
71 2848 : case TYPE_dbl:
72 2848 : v->val.dval = *(dbl *) p;
73 2848 : break;
74 306075 : case TYPE_lng:
75 306075 : v->val.lval = *(lng *) p;
76 306075 : break;
77 : #ifdef HAVE_HGE
78 1972 : case TYPE_hge:
79 1972 : v->val.hval = *(hge *) p;
80 1972 : break;
81 : #endif
82 106 : case TYPE_uuid:
83 106 : v->val.uval = *(uuid *) p;
84 106 : break;
85 4293708 : case TYPE_str:
86 4293708 : v->val.sval = (str) p;
87 4293708 : break;
88 255756 : case TYPE_ptr:
89 255756 : v->val.pval = *(ptr *) p;
90 255756 : break;
91 365 : default:
92 365 : v->val.pval = p;
93 365 : break;
94 : }
95 5226730 : v->len = ATOMlen(v->vtype, VALptr(v));
96 5226625 : return v;
97 : }
98 :
99 : /* Return a pointer to the value contained in V. Also see VALptr
100 : * which returns a const void *. */
101 : void *
102 32640296 : VALget(ValPtr v)
103 : {
104 32640296 : switch (ATOMstorage(v->vtype)) {
105 240 : case TYPE_void: return (void *) &v->val.oval;
106 0 : case TYPE_msk: return (void *) &v->val.mval;
107 4803058 : case TYPE_bte: return (void *) &v->val.btval;
108 117354 : case TYPE_sht: return (void *) &v->val.shval;
109 25408422 : case TYPE_int: return (void *) &v->val.ival;
110 1155 : case TYPE_flt: return (void *) &v->val.fval;
111 23645 : case TYPE_dbl: return (void *) &v->val.dval;
112 1334472 : case TYPE_lng: return (void *) &v->val.lval;
113 : #ifdef HAVE_HGE
114 30477 : case TYPE_hge: return (void *) &v->val.hval;
115 : #endif
116 68 : case TYPE_uuid: return (void *) &v->val.uval;
117 1 : case TYPE_ptr: return (void *) &v->val.pval;
118 921248 : case TYPE_str: return (void *) v->val.sval;
119 156 : default: return (void *) v->val.pval;
120 : }
121 : }
122 :
123 : /* Clear V to an empty value (type void, value nil), freeing any
124 : * memory allocated for external types. See VALempty for when V does
125 : * not yet contain a value. */
126 : void
127 44182208 : VALclear(ValPtr v)
128 : {
129 44182208 : if (ATOMextern(v->vtype)) {
130 6274274 : if (v->val.pval && v->val.pval != ATOMnilptr(v->vtype))
131 6115203 : GDKfree(v->val.pval);
132 : }
133 44182533 : VALempty(v);
134 44179760 : }
135 :
136 : /* Initialize V to an empty value (type void, value nil). See
137 : * VALclear for when V already contains a value. */
138 : void
139 61751336 : VALempty(ValPtr v)
140 : {
141 61751336 : v->len = 0;
142 61751336 : v->val.oval = oid_nil;
143 61751336 : v->vtype = TYPE_void;
144 61751336 : }
145 :
146 : /* Create a copy of S into D, allocating space for external values
147 : * (non-fixed sized values). See VALinit for a version where the
148 : * source is not in a VALRecord.
149 : *
150 : * Returns NULL In case of (malloc) failure. */
151 : ValPtr
152 35390845 : VALcopy(ValPtr d, const ValRecord *s)
153 : {
154 35390845 : if (!ATOMextern(s->vtype)) {
155 20858029 : *d = *s;
156 14532816 : } else if (s->val.pval == NULL) {
157 0 : return VALinit(d, s->vtype, ATOMnilptr(s->vtype));
158 14532816 : } else if (s->vtype == TYPE_str) {
159 14530239 : const char *p = s->val.sval;
160 14530239 : d->vtype = TYPE_str;
161 14530239 : d->len = strLen(p);
162 14530239 : d->val.sval = GDKmalloc(d->len);
163 14530782 : if (d->val.sval == NULL)
164 : return NULL;
165 14530782 : memcpy(d->val.sval, p, d->len);
166 : } else {
167 2577 : const void *p = s->val.pval;
168 2577 : d->vtype = s->vtype;
169 2577 : d->len = ATOMlen(d->vtype, p);
170 2577 : d->val.pval = GDKmalloc(d->len);
171 2577 : if (d->val.pval == NULL)
172 : return NULL;
173 2577 : memcpy(d->val.pval, p, d->len);
174 : }
175 : return d;
176 : }
177 :
178 : /* Create a copy of the type value combination in TPE/S, allocating
179 : * space for external values (non-fixed sized values). See VALcopy
180 : * for a version where the source is in a ValRecord, and see VALset
181 : * for a version where ownership of the source is transferred.
182 : *
183 : * Returns NULL in case of (malloc) failure. */
184 : ValPtr
185 5739888 : VALinit(ValPtr d, int tpe, const void *s)
186 : {
187 5739888 : switch (ATOMstorage(d->vtype = tpe)) {
188 0 : case TYPE_void:
189 0 : d->val.oval = *(const oid *) s;
190 0 : break;
191 0 : case TYPE_msk:
192 0 : d->val.mval = *(const msk *) s;
193 0 : break;
194 151428 : case TYPE_bte:
195 151428 : d->val.btval = *(const bte *) s;
196 151428 : break;
197 76122 : case TYPE_sht:
198 76122 : d->val.shval = *(const sht *) s;
199 76122 : break;
200 802153 : case TYPE_int:
201 802153 : d->val.ival = *(const int *) s;
202 802153 : break;
203 6392 : case TYPE_flt:
204 6392 : d->val.fval = *(const flt *) s;
205 6392 : break;
206 7729 : case TYPE_dbl:
207 7729 : d->val.dval = *(const dbl *) s;
208 7729 : break;
209 238627 : case TYPE_lng:
210 238627 : d->val.lval = *(const lng *) s;
211 238627 : break;
212 : #ifdef HAVE_HGE
213 1529 : case TYPE_hge:
214 1529 : d->val.hval = *(const hge *) s;
215 1529 : break;
216 : #endif
217 117 : case TYPE_uuid:
218 117 : d->val.uval = *(const uuid *) s;
219 117 : break;
220 4094575 : case TYPE_str:
221 4094575 : d->len = strLen(s);
222 4094575 : d->val.sval = GDKmalloc(d->len);
223 4094905 : if (d->val.sval == NULL)
224 : return NULL;
225 4094905 : memcpy(d->val.sval, s, d->len);
226 4094905 : return d;
227 360919 : case TYPE_ptr:
228 360919 : d->val.pval = *(const ptr *) s;
229 360919 : d->len = ATOMlen(tpe, *(const ptr *) s);
230 360919 : return d;
231 297 : default:
232 297 : assert(ATOMextern(ATOMstorage(tpe)));
233 297 : d->len = ATOMlen(tpe, s);
234 297 : d->val.pval = GDKmalloc(d->len);
235 297 : if (d->val.pval == NULL)
236 : return NULL;
237 297 : memcpy(d->val.pval, s, d->len);
238 297 : return d;
239 : }
240 1284097 : d->len = ATOMsize(d->vtype);
241 1284097 : return d;
242 : }
243 :
244 : /* Format the value in RES in the standard way for the type of RES
245 : * into a newly allocated buffer. Also see ATOMformat. */
246 : char *
247 17422 : VALformat(const ValRecord *res)
248 : {
249 17422 : return ATOMformat(res->vtype, VALptr(res));
250 : }
251 :
252 : /* Convert (cast) the value in T to the type TYP, do this in place.
253 : * Return a pointer to the converted value, or NULL if the conversion
254 : * didn't succeed. If the conversion didn't succeed, the original
255 : * value is not modified. Also see VARconvert. */
256 : ptr
257 295224 : VALconvert(int typ, ValPtr t)
258 : {
259 295224 : int src_tpe = t->vtype;
260 295224 : ValRecord dst;
261 :
262 295224 : dst.vtype = typ;
263 :
264 : /* first convert into a new location */
265 295224 : if (VARconvert(&dst, t, 0, 0, 0) != GDK_SUCCEED)
266 : return NULL;
267 :
268 : /* then maybe free the old */
269 295220 : if (src_tpe != dst.vtype &&
270 295210 : t->vtype != typ &&
271 295210 : dst.vtype != TYPE_void &&
272 295035 : (src_tpe >= TYPE_str || dst.vtype >= TYPE_str))
273 36873 : VALclear(t);
274 : /* and finally copy the result */
275 295220 : *t = dst;
276 : /* make sure we return the correct type (not the storage type) */
277 295220 : t->vtype = typ;
278 295220 : return VALget(t);
279 : }
280 :
281 : /* Compare two values in P and Q and return -1/0/1 depending on
282 : * whether P is less than, equal to, or larger than Q. Also return -1
283 : * if P or Q is NULL or NIL, or if the types of P and Q are not
284 : * equal. */
285 : int
286 1529830 : VALcmp(const ValRecord *p, const ValRecord *q)
287 : {
288 :
289 1529830 : int (*cmp)(const void *, const void *);
290 1529830 : int tpe;
291 1529830 : const void *nilptr, *pp, *pq;
292 :
293 1529830 : if (p == 0 || q == 0)
294 : return -1;
295 1529830 : if ((tpe = p->vtype) != q->vtype)
296 : return -1;
297 :
298 1529661 : if (tpe == TYPE_ptr)
299 : return 0; /* ignore comparing C pointers */
300 1529661 : cmp = ATOMcompare(tpe);
301 1529661 : nilptr = ATOMnilptr(tpe);
302 1529661 : pp = VALptr(p);
303 1529661 : pq = VALptr(q);
304 1529661 : if ((*cmp)(pp, nilptr) == 0 && (*cmp)(pq, nilptr) == 0)
305 : return 0; /* eq nil val */
306 1529661 : if ((*cmp)(pp, nilptr) == 0 || (*cmp)(pq, nilptr) == 0)
307 0 : return -1;
308 1529661 : return (*cmp)(pp, pq);
309 :
310 : }
311 :
312 : /* Return TRUE if the value in V is NIL. */
313 : bool
314 3676198 : VALisnil(const ValRecord *v)
315 : {
316 3676198 : switch (v->vtype) {
317 : case TYPE_void:
318 : return true;
319 0 : case TYPE_msk:
320 0 : return false;
321 9382 : case TYPE_bte:
322 9382 : return is_bte_nil(v->val.btval);
323 124060 : case TYPE_sht:
324 124060 : return is_sht_nil(v->val.shval);
325 1466263 : case TYPE_int:
326 1466263 : return is_int_nil(v->val.ival);
327 205510 : case TYPE_lng:
328 205510 : return is_lng_nil(v->val.lval);
329 : #ifdef HAVE_HGE
330 395 : case TYPE_hge:
331 395 : return is_hge_nil(v->val.hval);
332 : #endif
333 5 : case TYPE_uuid:
334 5 : return is_uuid_nil(v->val.uval);
335 6138 : case TYPE_flt:
336 6138 : return is_flt_nil(v->val.fval);
337 3186 : case TYPE_dbl:
338 3186 : return is_dbl_nil(v->val.dval);
339 6 : case TYPE_oid:
340 6 : return is_oid_nil(v->val.oval);
341 0 : case TYPE_ptr:
342 0 : return v->val.pval == NULL;
343 0 : case TYPE_bat:
344 0 : return is_bat_nil(v->val.bval);
345 : default:
346 1861245 : break;
347 : }
348 1861245 : return (*ATOMcompare(v->vtype))(VALptr(v), ATOMnilptr(v->vtype)) == 0;
349 : }
|