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 5653833 : VALset(ValPtr v, int t, ptr p)
51 : {
52 5653833 : assert(t < TYPE_any);
53 5653833 : v->bat = false;
54 5653833 : switch (ATOMstorage(v->vtype = t)) {
55 107856 : case TYPE_void:
56 107856 : v->val.oval = *(oid *) p;
57 107856 : break;
58 0 : case TYPE_msk:
59 0 : v->val.mval = *(msk *) p;
60 0 : break;
61 19983 : case TYPE_bte:
62 19983 : v->val.btval = *(bte *) p;
63 19983 : break;
64 15409 : case TYPE_sht:
65 15409 : v->val.shval = *(sht *) p;
66 15409 : break;
67 312207 : case TYPE_int:
68 312207 : v->val.ival = *(int *) p;
69 312207 : break;
70 2759 : case TYPE_flt:
71 2759 : v->val.fval = *(flt *) p;
72 2759 : break;
73 2836 : case TYPE_dbl:
74 2836 : v->val.dval = *(dbl *) p;
75 2836 : break;
76 295517 : case TYPE_lng:
77 295517 : v->val.lval = *(lng *) p;
78 295517 : break;
79 : #ifdef HAVE_HGE
80 1858 : case TYPE_hge:
81 1858 : v->val.hval = *(hge *) p;
82 1858 : break;
83 : #endif
84 105 : case TYPE_uuid:
85 105 : v->val.uval = *(uuid *) p;
86 105 : break;
87 4623816 : case TYPE_str:
88 4623816 : v->val.sval = (str) p;
89 4623816 : break;
90 271124 : case TYPE_ptr:
91 271124 : v->val.pval = *(ptr *) p;
92 271124 : break;
93 363 : default:
94 363 : v->val.pval = p;
95 363 : break;
96 : }
97 5653833 : v->len = ATOMlen(v->vtype, VALptr(v));
98 5653863 : 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 13338024 : VALget(ValPtr v)
105 : {
106 13338024 : assert(!v->bat);
107 13338024 : switch (ATOMstorage(v->vtype)) {
108 290 : case TYPE_void: return (void *) &v->val.oval;
109 0 : case TYPE_msk: return (void *) &v->val.mval;
110 9973044 : case TYPE_bte: return (void *) &v->val.btval;
111 185136 : case TYPE_sht: return (void *) &v->val.shval;
112 2231680 : case TYPE_int: return (void *) &v->val.ival;
113 1134 : case TYPE_flt: return (void *) &v->val.fval;
114 23672 : case TYPE_dbl: return (void *) &v->val.dval;
115 236912 : case TYPE_lng: return (void *) &v->val.lval;
116 : #ifdef HAVE_HGE
117 5632 : case TYPE_hge: return (void *) &v->val.hval;
118 : #endif
119 72 : case TYPE_uuid: return (void *) &v->val.uval;
120 1 : case TYPE_ptr: return (void *) &v->val.pval;
121 680316 : case TYPE_str: return (void *) v->val.sval;
122 135 : 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 52740882 : VALclear(ValPtr v)
131 : {
132 52740882 : if (!v->bat && ATOMextern(v->vtype)) {
133 7610584 : if (v->val.pval && v->val.pval != ATOMnilptr(v->vtype))
134 7454057 : GDKfree(v->val.pval);
135 : }
136 52743159 : VALempty(v);
137 52746514 : }
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 71376832 : VALempty(ValPtr v)
143 : {
144 71376832 : *v = (ValRecord) {
145 : .bat = false,
146 : .val.oval = oid_nil,
147 : .vtype = TYPE_void,
148 : };
149 71376832 : }
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 58753535 : VALcopy(ValPtr d, const ValRecord *s)
158 : {
159 58753535 : if (d == s)
160 : return d;
161 58750615 : d->bat = false;
162 58750615 : if (s->bat || !ATOMextern(s->vtype)) {
163 36267689 : *d = *s;
164 22482926 : } else if (s->val.pval == NULL) {
165 0 : return VALinit(d, s->vtype, ATOMnilptr(s->vtype));
166 22482926 : } else if (s->vtype == TYPE_str) {
167 22480362 : const char *p = s->val.sval;
168 22480362 : d->vtype = TYPE_str;
169 22480362 : d->len = strLen(p);
170 22480362 : d->val.sval = GDKmalloc(d->len);
171 22481319 : if (d->val.sval == NULL)
172 : return NULL;
173 22481319 : memcpy(d->val.sval, p, d->len);
174 : } else {
175 2564 : const void *p = s->val.pval;
176 2564 : d->vtype = s->vtype;
177 2564 : d->len = ATOMlen(d->vtype, p);
178 2564 : d->val.pval = GDKmalloc(d->len);
179 2565 : if (d->val.pval == NULL)
180 : return NULL;
181 2565 : 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 9694828 : VALinit(ValPtr d, int tpe, const void *s)
194 : {
195 9694828 : d->bat = false;
196 9694828 : 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 217079 : case TYPE_bte:
204 217079 : d->val.btval = *(const bte *) s;
205 217079 : break;
206 544053 : case TYPE_sht:
207 544053 : d->val.shval = *(const sht *) s;
208 544053 : break;
209 2900161 : case TYPE_int:
210 2900161 : d->val.ival = *(const int *) s;
211 2900161 : break;
212 12632 : case TYPE_flt:
213 12632 : d->val.fval = *(const flt *) s;
214 12632 : break;
215 10809 : case TYPE_dbl:
216 10809 : d->val.dval = *(const dbl *) s;
217 10809 : break;
218 278406 : case TYPE_lng:
219 278406 : d->val.lval = *(const lng *) s;
220 278406 : break;
221 : #ifdef HAVE_HGE
222 2111 : case TYPE_hge:
223 2111 : d->val.hval = *(const hge *) s;
224 2111 : break;
225 : #endif
226 118 : case TYPE_uuid:
227 118 : d->val.uval = *(const uuid *) s;
228 118 : break;
229 5325219 : case TYPE_str:
230 5325219 : d->len = strLen(s);
231 5325219 : d->val.sval = GDKmalloc(d->len);
232 5327038 : if (d->val.sval == NULL)
233 : return NULL;
234 5327038 : memcpy(d->val.sval, s, d->len);
235 5327038 : return d;
236 403964 : case TYPE_ptr:
237 403964 : d->val.pval = *(const ptr *) s;
238 403964 : d->len = ATOMlen(tpe, *(const ptr *) s);
239 403964 : return d;
240 276 : default:
241 276 : assert(ATOMextern(ATOMstorage(tpe)));
242 276 : d->len = ATOMlen(tpe, s);
243 276 : d->val.pval = GDKmalloc(d->len);
244 276 : if (d->val.pval == NULL)
245 : return NULL;
246 276 : memcpy(d->val.pval, s, d->len);
247 276 : return d;
248 : }
249 3965369 : d->len = ATOMsize(d->vtype);
250 3965369 : 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 24657 : VALformat(const ValRecord *res)
257 : {
258 24657 : if (res->bat) {
259 3753 : if (is_bat_nil(res->val.bval))
260 352 : return GDKstrdup("nil");
261 : else
262 3401 : return ATOMformat(TYPE_int, (const void *) &res->val.ival);
263 : } else
264 20904 : 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 281533 : VALconvert(int typ, ValPtr t)
273 : {
274 281533 : int src_tpe = t->vtype;
275 281533 : ValRecord dst = { .vtype = typ };
276 :
277 : /* first convert into a new location */
278 281533 : if (VARconvert(&dst, t, 0, 0, 0) != GDK_SUCCEED)
279 : return NULL;
280 :
281 : /* then maybe free the old */
282 281487 : if (src_tpe != dst.vtype &&
283 281469 : t->vtype != typ &&
284 281457 : dst.vtype != TYPE_void &&
285 281285 : (src_tpe >= TYPE_str || dst.vtype >= TYPE_str))
286 34155 : VALclear(t);
287 : /* and finally copy the result */
288 281487 : *t = dst;
289 : /* make sure we return the correct type (not the storage type) */
290 281487 : t->vtype = typ;
291 281487 : 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 1614106 : VALcmp(const ValRecord *p, const ValRecord *q)
300 : {
301 :
302 1614106 : int (*cmp)(const void *, const void *);
303 1614106 : int tpe;
304 1614106 : const void *nilptr, *pp, *pq;
305 :
306 1614106 : if (p == 0 || q == 0)
307 : return -1;
308 1614106 : if ((tpe = p->vtype) != q->vtype)
309 : return -1;
310 :
311 1614058 : if (tpe == TYPE_ptr)
312 : return 0; /* ignore comparing C pointers */
313 1614058 : cmp = ATOMcompare(tpe);
314 1614058 : nilptr = ATOMnilptr(tpe);
315 1614058 : pp = VALptr(p);
316 1614058 : pq = VALptr(q);
317 1614058 : if ((*cmp)(pp, nilptr) == 0 && (*cmp)(pq, nilptr) == 0)
318 : return 0; /* eq nil val */
319 1614058 : if ((*cmp)(pp, nilptr) == 0 || (*cmp)(pq, nilptr) == 0)
320 0 : return -1;
321 1614058 : return (*cmp)(pp, pq);
322 :
323 : }
324 :
325 : /* Return TRUE if the value in V is NIL. */
326 : bool
327 12139738 : VALisnil(const ValRecord *v)
328 : {
329 12139738 : if (v->bat)
330 0 : return is_bat_nil(v->val.bval);
331 12139738 : switch (v->vtype) {
332 : case TYPE_void:
333 : return true;
334 0 : case TYPE_msk:
335 0 : return false;
336 140408 : case TYPE_bte:
337 140408 : return is_bte_nil(v->val.btval);
338 1047261 : case TYPE_sht:
339 1047261 : return is_sht_nil(v->val.shval);
340 5710423 : case TYPE_int:
341 5710423 : return is_int_nil(v->val.ival);
342 261702 : case TYPE_lng:
343 261702 : return is_lng_nil(v->val.lval);
344 : #ifdef HAVE_HGE
345 2902 : case TYPE_hge:
346 2902 : return is_hge_nil(v->val.hval);
347 : #endif
348 5 : case TYPE_uuid:
349 5 : return is_uuid_nil(v->val.uval);
350 18600 : case TYPE_flt:
351 18600 : return is_flt_nil(v->val.fval);
352 9469 : case TYPE_dbl:
353 9469 : 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 4948956 : break;
360 : }
361 4948956 : return (*ATOMcompare(v->vtype))(VALptr(v), ATOMnilptr(v->vtype)) == 0;
362 : }
|