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 5225186 : VALset(ValPtr v, int t, ptr p)
51 : {
52 5225186 : assert(t < TYPE_any);
53 5225186 : v->bat = false;
54 5225186 : switch (ATOMstorage(v->vtype = t)) {
55 106844 : case TYPE_void:
56 106844 : v->val.oval = *(oid *) p;
57 106844 : break;
58 0 : case TYPE_msk:
59 0 : v->val.mval = *(msk *) p;
60 0 : break;
61 17878 : case TYPE_bte:
62 17878 : v->val.btval = *(bte *) p;
63 17878 : break;
64 14637 : case TYPE_sht:
65 14637 : v->val.shval = *(sht *) p;
66 14637 : break;
67 236030 : case TYPE_int:
68 236030 : v->val.ival = *(int *) p;
69 236030 : break;
70 2763 : case TYPE_flt:
71 2763 : v->val.fval = *(flt *) p;
72 2763 : break;
73 2674 : case TYPE_dbl:
74 2674 : v->val.dval = *(dbl *) p;
75 2674 : break;
76 260061 : case TYPE_lng:
77 260061 : v->val.lval = *(lng *) p;
78 260061 : break;
79 : #ifdef HAVE_HGE
80 1800 : case TYPE_hge:
81 1800 : v->val.hval = *(hge *) p;
82 1800 : break;
83 : #endif
84 106 : case TYPE_uuid:
85 106 : v->val.uval = *(uuid *) p;
86 106 : break;
87 4320319 : case TYPE_str:
88 4320319 : v->val.sval = (str) p;
89 4320319 : break;
90 261706 : case TYPE_ptr:
91 261706 : v->val.pval = *(ptr *) p;
92 261706 : break;
93 368 : default:
94 368 : v->val.pval = p;
95 368 : break;
96 : }
97 5225186 : v->len = ATOMlen(v->vtype, VALptr(v));
98 5225228 : return v;
99 : }
100 :
101 : /* Return a pointer to the value contained in V. Also see VALptr
102 : * which returns a const void *. */
103 : void *
104 8926837 : VALget(ValPtr v)
105 : {
106 8926837 : assert(!v->bat);
107 8926837 : switch (ATOMstorage(v->vtype)) {
108 280 : case TYPE_void: return (void *) &v->val.oval;
109 0 : case TYPE_msk: return (void *) &v->val.mval;
110 4798707 : case TYPE_bte: return (void *) &v->val.btval;
111 179101 : case TYPE_sht: return (void *) &v->val.shval;
112 2088127 : case TYPE_int: return (void *) &v->val.ival;
113 1116 : case TYPE_flt: return (void *) &v->val.fval;
114 22831 : case TYPE_dbl: return (void *) &v->val.dval;
115 1229262 : case TYPE_lng: return (void *) &v->val.lval;
116 : #ifdef HAVE_HGE
117 5610 : case TYPE_hge: return (void *) &v->val.hval;
118 : #endif
119 56 : case TYPE_uuid: return (void *) &v->val.uval;
120 1 : case TYPE_ptr: return (void *) &v->val.pval;
121 601590 : case TYPE_str: return (void *) v->val.sval;
122 156 : default: return (void *) v->val.pval;
123 : }
124 : }
125 :
126 : /* Clear V to an empty value (type void, value nil), freeing any
127 : * memory allocated for external types. See VALempty for when V does
128 : * not yet contain a value. */
129 : void
130 49712721 : VALclear(ValPtr v)
131 : {
132 49712721 : if (!v->bat && ATOMextern(v->vtype)) {
133 7167281 : if (v->val.pval && v->val.pval != ATOMnilptr(v->vtype))
134 7009123 : GDKfree(v->val.pval);
135 : }
136 49715197 : VALempty(v);
137 49716148 : }
138 :
139 : /* Initialize V to an empty value (type void, value nil). See
140 : * VALclear for when V already contains a value. */
141 : void
142 67111649 : VALempty(ValPtr v)
143 : {
144 67111649 : *v = (ValRecord) {
145 : .bat = false,
146 : .val.oval = oid_nil,
147 : .vtype = TYPE_void,
148 : };
149 67111649 : }
150 :
151 : /* Create a copy of S into D, allocating space for external values
152 : * (non-fixed sized values). See VALinit for a version where the
153 : * source is not in a VALRecord.
154 : *
155 : * Returns NULL In case of (malloc) failure. */
156 : ValPtr
157 38647953 : VALcopy(ValPtr d, const ValRecord *s)
158 : {
159 38647953 : if (d == s)
160 : return d;
161 38645049 : d->bat = false;
162 38645049 : if (s->bat || !ATOMextern(s->vtype)) {
163 25118675 : *d = *s;
164 13526374 : } else if (s->val.pval == NULL) {
165 0 : return VALinit(d, s->vtype, ATOMnilptr(s->vtype));
166 13526374 : } else if (s->vtype == TYPE_str) {
167 13523791 : const char *p = s->val.sval;
168 13523791 : d->vtype = TYPE_str;
169 13523791 : d->len = strLen(p);
170 13523791 : d->val.sval = GDKmalloc(d->len);
171 13524564 : if (d->val.sval == NULL)
172 : return NULL;
173 13524564 : memcpy(d->val.sval, p, d->len);
174 : } else {
175 2583 : const void *p = s->val.pval;
176 2583 : d->vtype = s->vtype;
177 2583 : d->len = ATOMlen(d->vtype, p);
178 2583 : d->val.pval = GDKmalloc(d->len);
179 2583 : if (d->val.pval == NULL)
180 : return NULL;
181 2583 : memcpy(d->val.pval, p, d->len);
182 : }
183 : return d;
184 : }
185 :
186 : /* Create a copy of the type value combination in TPE/S, allocating
187 : * space for external values (non-fixed sized values). See VALcopy
188 : * for a version where the source is in a ValRecord, and see VALset
189 : * for a version where ownership of the source is transferred.
190 : *
191 : * Returns NULL in case of (malloc) failure. */
192 : ValPtr
193 9139108 : VALinit(ValPtr d, int tpe, const void *s)
194 : {
195 9139108 : d->bat = false;
196 9139108 : switch (ATOMstorage(d->vtype = tpe)) {
197 0 : case TYPE_void:
198 0 : d->val.oval = *(const oid *) s;
199 0 : break;
200 0 : case TYPE_msk:
201 0 : d->val.mval = *(const msk *) s;
202 0 : break;
203 198460 : case TYPE_bte:
204 198460 : d->val.btval = *(const bte *) s;
205 198460 : break;
206 516484 : case TYPE_sht:
207 516484 : d->val.shval = *(const sht *) s;
208 516484 : break;
209 2830499 : case TYPE_int:
210 2830499 : d->val.ival = *(const int *) s;
211 2830499 : break;
212 12574 : case TYPE_flt:
213 12574 : d->val.fval = *(const flt *) s;
214 12574 : break;
215 10066 : case TYPE_dbl:
216 10066 : d->val.dval = *(const dbl *) s;
217 10066 : break;
218 217939 : case TYPE_lng:
219 217939 : d->val.lval = *(const lng *) s;
220 217939 : break;
221 : #ifdef HAVE_HGE
222 2217 : case TYPE_hge:
223 2217 : d->val.hval = *(const hge *) s;
224 2217 : break;
225 : #endif
226 105 : case TYPE_uuid:
227 105 : d->val.uval = *(const uuid *) s;
228 105 : break;
229 5004753 : case TYPE_str:
230 5004753 : d->len = strLen(s);
231 5004753 : d->val.sval = GDKmalloc(d->len);
232 5006710 : if (d->val.sval == NULL)
233 : return NULL;
234 5006710 : memcpy(d->val.sval, s, d->len);
235 5006710 : return d;
236 345714 : case TYPE_ptr:
237 345714 : d->val.pval = *(const ptr *) s;
238 345714 : d->len = ATOMlen(tpe, *(const ptr *) s);
239 345714 : return d;
240 297 : default:
241 297 : assert(ATOMextern(ATOMstorage(tpe)));
242 297 : d->len = ATOMlen(tpe, s);
243 297 : d->val.pval = GDKmalloc(d->len);
244 297 : if (d->val.pval == NULL)
245 : return NULL;
246 297 : memcpy(d->val.pval, s, d->len);
247 297 : return d;
248 : }
249 3788344 : d->len = ATOMsize(d->vtype);
250 3788344 : return d;
251 : }
252 :
253 : /* Format the value in RES in the standard way for the type of RES
254 : * into a newly allocated buffer. Also see ATOMformat. */
255 : char *
256 18650 : VALformat(const ValRecord *res)
257 : {
258 18650 : if (res->bat) {
259 3926 : if (is_bat_nil(res->val.bval))
260 367 : return GDKstrdup("nil");
261 : else
262 3559 : return ATOMformat(TYPE_int, (const void *) &res->val.ival);
263 : } else
264 14724 : return ATOMformat(res->vtype, VALptr(res));
265 : }
266 :
267 : /* Convert (cast) the value in T to the type TYP, do this in place.
268 : * Return a pointer to the converted value, or NULL if the conversion
269 : * didn't succeed. If the conversion didn't succeed, the original
270 : * value is not modified. Also see VARconvert. */
271 : ptr
272 283122 : VALconvert(int typ, ValPtr t)
273 : {
274 283122 : int src_tpe = t->vtype;
275 283122 : ValRecord dst = { .vtype = typ };
276 :
277 : /* first convert into a new location */
278 283122 : if (VARconvert(&dst, t, 0, 0, 0) != GDK_SUCCEED)
279 : return NULL;
280 :
281 : /* then maybe free the old */
282 283062 : if (src_tpe != dst.vtype &&
283 283044 : t->vtype != typ &&
284 283079 : dst.vtype != TYPE_void &&
285 282904 : (src_tpe >= TYPE_str || dst.vtype >= TYPE_str))
286 33669 : VALclear(t);
287 : /* and finally copy the result */
288 283062 : *t = dst;
289 : /* make sure we return the correct type (not the storage type) */
290 283062 : t->vtype = typ;
291 283062 : return VALget(t);
292 : }
293 :
294 : /* Compare two values in P and Q and return -1/0/1 depending on
295 : * whether P is less than, equal to, or larger than Q. Also return -1
296 : * if P or Q is NULL or NIL, or if the types of P and Q are not
297 : * equal. */
298 : int
299 1551046 : VALcmp(const ValRecord *p, const ValRecord *q)
300 : {
301 :
302 1551046 : int (*cmp)(const void *, const void *);
303 1551046 : int tpe;
304 1551046 : const void *nilptr, *pp, *pq;
305 :
306 1551046 : if (p == 0 || q == 0)
307 : return -1;
308 1551046 : if ((tpe = p->vtype) != q->vtype)
309 : return -1;
310 :
311 1550927 : if (tpe == TYPE_ptr)
312 : return 0; /* ignore comparing C pointers */
313 1550927 : cmp = ATOMcompare(tpe);
314 1550927 : nilptr = ATOMnilptr(tpe);
315 1550927 : pp = VALptr(p);
316 1550927 : pq = VALptr(q);
317 1550927 : if ((*cmp)(pp, nilptr) == 0 && (*cmp)(pq, nilptr) == 0)
318 : return 0; /* eq nil val */
319 1550925 : if ((*cmp)(pp, nilptr) == 0 || (*cmp)(pq, nilptr) == 0)
320 0 : return -1;
321 1550926 : return (*cmp)(pp, pq);
322 :
323 : }
324 :
325 : /* Return TRUE if the value in V is NIL. */
326 : bool
327 10471380 : VALisnil(const ValRecord *v)
328 : {
329 10471380 : if (v->bat)
330 0 : return is_bat_nil(v->val.bval);
331 10471380 : switch (v->vtype) {
332 : case TYPE_void:
333 : return true;
334 0 : case TYPE_msk:
335 0 : return false;
336 106687 : case TYPE_bte:
337 106687 : return is_bte_nil(v->val.btval);
338 993546 : case TYPE_sht:
339 993546 : return is_sht_nil(v->val.shval);
340 5537006 : case TYPE_int:
341 5537006 : return is_int_nil(v->val.ival);
342 257933 : case TYPE_lng:
343 257933 : return is_lng_nil(v->val.lval);
344 : #ifdef HAVE_HGE
345 2869 : case TYPE_hge:
346 2869 : return is_hge_nil(v->val.hval);
347 : #endif
348 5 : case TYPE_uuid:
349 5 : return is_uuid_nil(v->val.uval);
350 18508 : case TYPE_flt:
351 18508 : return is_flt_nil(v->val.fval);
352 8787 : case TYPE_dbl:
353 8787 : return is_dbl_nil(v->val.dval);
354 10 : case TYPE_oid:
355 10 : return is_oid_nil(v->val.oval);
356 0 : case TYPE_ptr:
357 0 : return v->val.pval == NULL;
358 : default:
359 3546027 : break;
360 : }
361 3546027 : return (*ATOMcompare(v->vtype))(VALptr(v), ATOMnilptr(v->vtype)) == 0;
362 : }
|