LCOV - code coverage report
Current view: top level - gdk - gdk_value.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 178 196 90.8 %
Date: 2024-04-25 20:03:45 Functions: 10 10 100.0 %

          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             : }

Generated by: LCOV version 1.14