LCOV - code coverage report
Current view: top level - gdk - gdk_value.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 165 191 86.4 %
Date: 2021-09-14 19:48:19 Functions: 10 10 100.0 %

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

Generated by: LCOV version 1.14