LCOV - code coverage report
Current view: top level - monetdb5/modules/atoms - uuid.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 74 229 32.3 %
Date: 2021-10-13 02:24:04 Functions: 8 13 61.5 %

          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             :  * K.S. Mullender & A. de Rijke
      11             :  * The UUID module
      12             :  * The UUID module contains a wrapper for all function in
      13             :  * libuuid.
      14             :  */
      15             : 
      16             : #include "monetdb_config.h"
      17             : #if defined(HAVE_GETENTROPY) && defined(HAVE_SYS_RANDOM_H)
      18             : #include <sys/random.h>
      19             : #endif
      20             : #include "mal.h"
      21             : #include "mal_exception.h"
      22             : #include "mal_atom.h"                 /* for malAtomSize */
      23             : 
      24             : #if !defined(HAVE_UUID) && !defined(HAVE_GETENTROPY) && defined(HAVE_RAND_S)
      25             : static inline bool
      26             : generate_uuid(uuid *U)
      27             : {
      28             :         union {
      29             :                 unsigned int randbuf[4];
      30             :                 unsigned char uuid[16];
      31             :         } u;
      32             :         for (int i = 0; i < 4; i++)
      33             :                 if (rand_s(&u.randbuf[i]) != 0)
      34             :                         return false;
      35             :         /* make sure this is a variant 1 UUID (RFC 4122/DCE 1.1) */
      36             :         u.uuid[8] = (u.uuid[8] & 0x3F) | 0x80;
      37             :         /* make sure this is version 4 (random UUID) */
      38             :         u.uuid[6] = (u.uuid[6] & 0x0F) | 0x40;
      39             :         memcpy(U->u, u.uuid, 16);
      40             :         return true;
      41             : }
      42             : #endif
      43             : 
      44             : /**
      45             :  * Returns the string representation of the given uuid value.
      46             :  * Warning: GDK function
      47             :  * Returns the length of the string
      48             :  */
      49             : static inline void
      50             : UUIDgenerateUuid_internal(uuid *u)
      51             : {
      52             : #ifdef HAVE_UUID
      53         102 :         uuid_generate(u->u);
      54             : #else
      55             : #if defined(HAVE_GETENTROPY)
      56             :         if (getentropy(u->u, 16) == 0) {
      57             :                 /* make sure this is a variant 1 UUID (RFC 4122/DCE 1.1) */
      58             :                 u->u[8] = (u->u[8] & 0x3F) | 0x80;
      59             :                 /* make sure this is version 4 (random UUID) */
      60             :                 u->u[6] = (u->u[6] & 0x0F) | 0x40;
      61             :         } else
      62             : #elif defined(HAVE_RAND_S)
      63             :         if (!generate_uuid(u))
      64             : #endif
      65             :         {
      66             :                 /* generate something like this:
      67             :                  * cefa7a9c-1dd2-41b2-8350-880020adbeef
      68             :                  * ("%08x-%04x-%04x-%04x-%012x") */
      69             :                 for (int i = 0; i < 16; i++) {
      70             :                         int r = rand();
      71             :                         u->u[i++] = (unsigned char) (r >> 8);
      72             :                         u->u[i++] = (unsigned char) r;
      73             :                 }
      74             :                 /* make sure this is a variant 1 UUID (RFC 4122/DCE 1.1) */
      75             :                 u->u[8] = (u->u[8] & 0x3F) | 0x80;
      76             :                 /* make sure this is version 4 (random UUID) */
      77             :                 u->u[6] = (u->u[6] & 0x0F) | 0x40;
      78             :         }
      79             : #endif
      80             : }
      81             : 
      82             : static str
      83         102 : UUIDgenerateUuid(uuid *retval)
      84             : {
      85             :         UUIDgenerateUuid_internal(retval);
      86         102 :         return MAL_SUCCEED;
      87             : }
      88             : 
      89             : static str
      90           0 : UUIDgenerateUuidInt(uuid *retval, int *d)
      91             : {
      92             :         (void)d;
      93           0 :         return UUIDgenerateUuid(retval);
      94             : }
      95             : 
      96             : static inline bit
      97          99 : isaUUID(const char *s)
      98             : {
      99          99 :         uuid u, *pu = &u;
     100          99 :         size_t l = UUID_SIZE;
     101          99 :         ssize_t res = BATatoms[TYPE_uuid].atomFromStr(s, &l, (void **) &pu, false);
     102             : 
     103          99 :         if (res > 1)
     104             :                 return true;
     105          83 :         else if (res == 1)
     106          32 :                 return bit_nil;
     107             :         else
     108             :                 return false;
     109             : }
     110             : 
     111             : static str
     112           0 : UUIDgenerateUuidInt_bulk(bat *ret, const bat *bid)
     113             : {
     114             :         BAT *b = NULL, *bn = NULL;
     115             :         BUN n = 0;
     116             :         str msg = MAL_SUCCEED;
     117             :         uuid *restrict bnt = NULL;
     118             : 
     119           0 :         if ((b = BBPquickdesc(*bid)) == NULL)   {
     120           0 :                 msg = createException(MAL, "uuid.generateuuidint_bulk", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     121           0 :                 goto bailout;
     122             :         }
     123           0 :         n = BATcount(b);
     124           0 :         if ((bn = COLnew(b->hseqbase, TYPE_uuid, n, TRANSIENT)) == NULL) {
     125           0 :                 msg = createException(MAL, "uuid.generateuuidint_bulk", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     126           0 :                 goto bailout;
     127             :         }
     128           0 :         bnt = Tloc(bn, 0);
     129           0 :         for (BUN i = 0 ; i < n ; i++)
     130           0 :                 UUIDgenerateUuid_internal(&(bnt[i]));
     131           0 :         bn->tnonil = true;
     132           0 :         bn->tnil = false;
     133           0 :         BATsetcount(bn, n);
     134           0 :         bn->tsorted = n <= 1;
     135           0 :         bn->trevsorted = n <= 1;
     136           0 :         bn->tkey = n <= 1;
     137             : 
     138           0 : bailout:
     139           0 :         if (msg && bn)
     140           0 :                 BBPreclaim(bn);
     141           0 :         else if (bn)
     142           0 :                 BBPkeepref(*ret = bn->batCacheid);
     143           0 :         return msg;
     144             : }
     145             : 
     146             : static str
     147          32 : UUIDisaUUID(bit *retval, str *s)
     148             : {
     149          32 :         *retval = isaUUID(*s);
     150          32 :         return MAL_SUCCEED;
     151             : }
     152             : 
     153             : static str
     154          17 : UUIDisaUUID_bulk(bat *ret, const bat *bid)
     155             : {
     156             :         BAT *b = NULL, *bn = NULL;
     157             :         BUN q;
     158             :         bit *restrict dst;
     159             :         str msg = MAL_SUCCEED;
     160             :         BATiter bi;
     161             : 
     162          17 :         if ((b = BATdescriptor(*bid)) == NULL)  {
     163           0 :                 msg = createException(MAL, "uuid.isaUUID_bulk", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     164           0 :                 goto bailout;
     165             :         }
     166          17 :         q = BATcount(b);
     167          17 :         if ((bn = COLnew(b->hseqbase, TYPE_bit, q, TRANSIENT)) == NULL) {
     168           0 :                 msg = createException(MAL, "uuid.isaUUID_bulk", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     169           0 :                 goto bailout;
     170             :         }
     171          17 :         dst = Tloc(bn, 0);
     172          17 :         bi = bat_iterator(b);
     173          84 :         for (BUN p = 0 ; p < q ; p++)
     174          67 :                 dst[p] = isaUUID(BUNtvar(bi, p));
     175          17 :         bat_iterator_end(&bi);
     176          17 :         bn->tnonil = b->tnonil;
     177          17 :         bn->tnil = b->tnil;
     178          17 :         BATsetcount(bn, q);
     179          17 :         bn->tsorted = bn->trevsorted = q < 2;
     180          17 :         bn->tkey = false;
     181          17 : bailout:
     182          17 :         if (b)
     183          17 :                 BBPunfix(b->batCacheid);
     184          17 :         if (bn)                                         /* implies msg==MAL_SUCCEED */
     185          17 :                 BBPkeepref(*ret = bn->batCacheid);
     186          17 :         return msg;
     187             : }
     188             : 
     189             : static str
     190           0 : UUIDuuid2uuid(uuid *retval, uuid *i)
     191             : {
     192           0 :         *retval = *i;
     193           0 :         return MAL_SUCCEED;
     194             : }
     195             : 
     196             : static str
     197           0 : UUIDuuid2uuid_bulk(bat *res, const bat *bid, const bat *sid)
     198             : {
     199             :         BAT *b = NULL, *s = NULL, *dst = NULL;
     200             :         uuid *restrict bv, *restrict dv;
     201             :         str msg = NULL;
     202             :         struct canditer ci;
     203             :         BUN q = 0;
     204             :         oid off;
     205             :         bool nils = false;
     206             :         BATiter bi;
     207             : 
     208           0 :         if (sid && !is_bat_nil(*sid)) {
     209           0 :                 if ((s = BATdescriptor(*sid)) == NULL) {
     210           0 :                         msg = createException(SQL, "batcalc.uuid2uuidbulk", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     211           0 :                         goto bailout;
     212             :                 }
     213             :         } else {
     214           0 :                 BBPretain(*res = *bid); /* nothing to convert, return */
     215           0 :                 return MAL_SUCCEED;
     216             :         }
     217           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     218           0 :                 msg = createException(SQL, "batcalc.uuid2uuidbulk", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     219           0 :                 goto bailout;
     220             :         }
     221           0 :         off = b->hseqbase;
     222           0 :         q = canditer_init(&ci, b, s);
     223           0 :         if (!(dst = COLnew(ci.hseq, TYPE_uuid, q, TRANSIENT))) {
     224           0 :                 msg = createException(SQL, "batcalc.uuid2uuidbulk", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     225           0 :                 goto bailout;
     226             :         }
     227             : 
     228           0 :         bi = bat_iterator(b);
     229           0 :         bv = bi.base;
     230           0 :         dv = Tloc(dst, 0);
     231           0 :         if (ci.tpe == cand_dense) {
     232           0 :                 for (BUN i = 0; i < q; i++) {
     233           0 :                         oid p = (canditer_next_dense(&ci) - off);
     234           0 :                         uuid v = bv[p];
     235             : 
     236           0 :                         dv[i] = v;
     237           0 :                         nils |= is_uuid_nil(v);
     238             :                 }
     239             :         } else {
     240           0 :                 for (BUN i = 0; i < q; i++) {
     241           0 :                         oid p = (canditer_next(&ci) - off);
     242           0 :                         uuid v = bv[p];
     243             : 
     244           0 :                         dv[i] = v;
     245           0 :                         nils |= is_uuid_nil(v);
     246             :                 }
     247             :         }
     248           0 :         bat_iterator_end(&bi);
     249             : 
     250           0 : bailout:
     251           0 :         if (dst) {                                      /* implies msg==MAL_SUCCEED */
     252           0 :                 BATsetcount(dst, q);
     253           0 :                 dst->tnil = nils;
     254           0 :                 dst->tnonil = !nils;
     255           0 :                 dst->tkey = b->tkey;
     256           0 :                 dst->tsorted = b->tsorted;
     257           0 :                 dst->trevsorted = b->trevsorted;
     258           0 :                 BBPkeepref(*res = dst->batCacheid);
     259             :         }
     260           0 :         if (b)
     261           0 :                 BBPunfix(b->batCacheid);
     262           0 :         if (s)
     263           0 :                 BBPunfix(s->batCacheid);
     264             :         return msg;
     265             : }
     266             : 
     267             : static str
     268          46 : UUIDstr2uuid(uuid *retval, str *s)
     269             : {
     270          46 :         size_t l = UUID_SIZE;
     271             : 
     272          46 :         if (BATatoms[TYPE_uuid].atomFromStr(*s, &l, (void **) &retval, false) > 0) {
     273             :                 return MAL_SUCCEED;
     274             :         }
     275           6 :         throw(MAL, "uuid.uuid", "Not a UUID");
     276             : }
     277             : 
     278             : static str
     279           2 : UUIDstr2uuid_bulk(bat *res, const bat *bid, const bat *sid)
     280             : {
     281             :         BAT *b = NULL, *s = NULL, *dst = NULL;
     282             :         BATiter bi;
     283             :         str msg = NULL;
     284             :         uuid *restrict vals;
     285             :         struct canditer ci;
     286             :         BUN q = 0;
     287             :         oid off;
     288             :         bool nils = false;
     289           2 :         size_t l = UUID_SIZE;
     290           2 :         ssize_t (*conv)(const char *, size_t *, void **, bool) = BATatoms[TYPE_uuid].atomFromStr;
     291             : 
     292           2 :         if ((b = BATdescriptor(*bid)) == NULL) {
     293           0 :                 msg = createException(SQL, "batcalc.str2uuidbulk", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     294           0 :                 goto bailout;
     295             :         }
     296           2 :         if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
     297           0 :                 msg = createException(SQL, "batcalc.str2uuidbulk", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     298           0 :                 goto bailout;
     299             :         }
     300           2 :         off = b->hseqbase;
     301           2 :         q = canditer_init(&ci, b, s);
     302           2 :         if (!(dst = COLnew(ci.hseq, TYPE_uuid, q, TRANSIENT))) {
     303           0 :                 msg = createException(SQL, "batcalc.str2uuidbulk", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     304           0 :                 goto bailout;
     305             :         }
     306             : 
     307           2 :         bi = bat_iterator(b);
     308           2 :         vals = Tloc(dst, 0);
     309           2 :         if (ci.tpe == cand_dense) {
     310           4 :                 for (BUN i = 0; i < q; i++) {
     311           2 :                         oid p = (canditer_next_dense(&ci) - off);
     312           2 :                         str v = (str) BUNtvar(bi, p);
     313           2 :                         uuid *up = &vals[i], **pp = &up;
     314             : 
     315           2 :                         if (conv(v, &l, (void **) pp, false) <= 0) {
     316           0 :                                 msg = createException(SQL, "batcalc.str2uuidbulk", SQLSTATE(42000) "Not a UUID");
     317           0 :                                 bat_iterator_end(&bi);
     318           0 :                                 goto bailout;
     319             :                         }
     320           2 :                         nils |= strNil(v);
     321             :                 }
     322             :         } else {
     323           0 :                 for (BUN i = 0; i < q; i++) {
     324           0 :                         oid p = (canditer_next(&ci) - off);
     325           0 :                         str v = (str) BUNtvar(bi, p);
     326           0 :                         uuid *up = &vals[i], **pp = &up;
     327             : 
     328           0 :                         if (conv(v, &l, (void **) pp, false) <= 0) {
     329           0 :                                 msg = createException(SQL, "batcalc.str2uuidbulk", SQLSTATE(42000) "Not a UUID");
     330           0 :                                 bat_iterator_end(&bi);
     331           0 :                                 goto bailout;
     332             :                         }
     333           0 :                         nils |= strNil(v);
     334             :                 }
     335             :         }
     336           2 :         bat_iterator_end(&bi);
     337             : 
     338           2 : bailout:
     339           2 :         if (dst && !msg) {
     340           2 :                 BATsetcount(dst, q);
     341           2 :                 dst->tnil = nils;
     342           2 :                 dst->tnonil = !nils;
     343           2 :                 dst->tkey = b->tkey;
     344           2 :                 dst->tsorted = BATcount(dst) <= 1;
     345           2 :                 dst->trevsorted = BATcount(dst) <= 1;
     346           2 :                 BBPkeepref(*res = dst->batCacheid);
     347           0 :         } else if (dst)
     348           0 :                 BBPreclaim(dst);
     349           2 :         if (b)
     350           2 :                 BBPunfix(b->batCacheid);
     351           2 :         if (s)
     352           0 :                 BBPunfix(s->batCacheid);
     353           2 :         return msg;
     354             : }
     355             : 
     356             : static str
     357         101 : UUIDuuid2str(str *retval, const uuid *u)
     358             : {
     359         101 :         size_t l = 0;
     360         101 :         *retval = NULL;
     361         101 :         if (BATatoms[TYPE_uuid].atomToStr(retval, &l, u, false) < 0)
     362           0 :                 throw(MAL, "uuid.str", GDK_EXCEPTION);
     363             :         return MAL_SUCCEED;
     364             : }
     365             : 
     366             : static str
     367           0 : UUIDuuid2str_bulk(bat *res, const bat *bid, const bat *sid)
     368             : {
     369             :         BAT *b = NULL, *s = NULL, *dst = NULL;
     370             :         str msg = NULL;
     371             :         uuid *restrict vals;
     372             :         BUN q = 0;
     373             :         struct canditer ci;
     374             :         oid off;
     375             :         bool nils = false;
     376           0 :         char buf[UUID_STRLEN + 2], *pbuf = buf;
     377           0 :         size_t l = sizeof(buf);
     378           0 :         ssize_t (*conv)(char **, size_t *, const void *, bool) = BATatoms[TYPE_uuid].atomToStr;
     379             :         BATiter bi;
     380             : 
     381           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     382           0 :                 msg = createException(SQL, "batcalc.uuid2strbulk", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     383           0 :                 goto bailout;
     384             :         }
     385           0 :         if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
     386           0 :                 msg = createException(SQL, "batcalc.uuid2strbulk", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     387           0 :                 goto bailout;
     388             :         }
     389           0 :         off = b->hseqbase;
     390           0 :         q = canditer_init(&ci, b, s);
     391           0 :         if (!(dst = COLnew(ci.hseq, TYPE_str, q, TRANSIENT))) {
     392           0 :                 msg = createException(SQL, "batcalc.uuid2strbulk", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     393           0 :                 goto bailout;
     394             :         }
     395             : 
     396           0 :         bi = bat_iterator(b);
     397           0 :         vals = bi.base;
     398           0 :         if (ci.tpe == cand_dense) {
     399           0 :                 for (BUN i = 0; i < q; i++) {
     400           0 :                         oid p = (canditer_next_dense(&ci) - off);
     401           0 :                         uuid v = vals[p];
     402             : 
     403           0 :                         if (conv(&pbuf, &l, &v, false) < 0) { /* it should never be reallocated */
     404           0 :                                 msg = createException(MAL, "batcalc.uuid2strbulk", GDK_EXCEPTION);
     405           0 :                                 bat_iterator_end(&bi);
     406           0 :                                 goto bailout;
     407             :                         }
     408           0 :                         if (tfastins_nocheckVAR(dst, i, buf) != GDK_SUCCEED) {
     409           0 :                                 msg = createException(SQL, "batcalc.uuid2strbulk", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     410           0 :                                 bat_iterator_end(&bi);
     411           0 :                                 goto bailout;
     412             :                         }
     413             :                         nils |= strNil(buf);
     414             :                 }
     415             :         } else {
     416           0 :                 for (BUN i = 0; i < q; i++) {
     417           0 :                         oid p = (canditer_next(&ci) - off);
     418           0 :                         uuid v = vals[p];
     419             : 
     420           0 :                         if (conv(&pbuf, &l, &v, false) < 0) { /* it should never be reallocated */
     421           0 :                                 msg = createException(MAL, "batcalc.uuid2strbulk", GDK_EXCEPTION);
     422           0 :                                 bat_iterator_end(&bi);
     423           0 :                                 goto bailout;
     424             :                         }
     425           0 :                         if (tfastins_nocheckVAR(dst, i, buf) != GDK_SUCCEED) {
     426           0 :                                 msg = createException(SQL, "batcalc.uuid2strbulk", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     427           0 :                                 bat_iterator_end(&bi);
     428           0 :                                 goto bailout;
     429             :                         }
     430           0 :                         nils |= strNil(buf);
     431             :                 }
     432             :         }
     433           0 :         bat_iterator_end(&bi);
     434             : 
     435           0 : bailout:
     436           0 :         if (dst && !msg) {
     437           0 :                 BATsetcount(dst, q);
     438           0 :                 dst->tnil = nils;
     439           0 :                 dst->tnonil = !nils;
     440           0 :                 dst->tkey = b->tkey;
     441           0 :                 dst->tsorted = BATcount(dst) <= 1;
     442           0 :                 dst->trevsorted = BATcount(dst) <= 1;
     443           0 :                 BBPkeepref(*res = dst->batCacheid);
     444           0 :         } else if (dst)
     445           0 :                 BBPreclaim(dst);
     446           0 :         if (b)
     447           0 :                 BBPunfix(b->batCacheid);
     448           0 :         if (s)
     449           0 :                 BBPunfix(s->batCacheid);
     450           0 :         return msg;
     451             : }
     452             : 
     453             : #include "mel.h"
     454             : mel_func uuid_init_funcs[] = {
     455             :  command("uuid", "new", UUIDgenerateUuid, true, "Generate a new uuid", args(1,1, arg("",uuid))),
     456             :  command("uuid", "new", UUIDgenerateUuidInt, true, "Generate a new uuid (dummy version for side effect free multiplex loop)", args(1,2, arg("",uuid),arg("d",int))),
     457             :  command("batuuid", "new", UUIDgenerateUuidInt_bulk, true, "Generate a new uuid (dummy version for side effect free multiplex loop)", args(1,2, batarg("",uuid),batarg("d",int))),
     458             :  command("uuid", "uuid", UUIDstr2uuid, false, "Coerce a string to a uuid, validating its format", args(1,2, arg("",uuid),arg("s",str))),
     459             :  command("uuid", "str", UUIDuuid2str, false, "Coerce a uuid to its string type", args(1,2, arg("",str),arg("u",uuid))),
     460             :  command("uuid", "isaUUID", UUIDisaUUID, false, "Test a string for a UUID format", args(1,2, arg("",bit),arg("u",str))),
     461             :  command("batuuid", "isaUUID", UUIDisaUUID_bulk, false, "Test a string for a UUID format", args(1,2, batarg("",bit),batarg("u",str))),
     462             :  command("calc", "uuid", UUIDstr2uuid, false, "Coerce a string to a uuid, validating its format", args(1,2, arg("",uuid),arg("s",str))),
     463             :  command("batcalc", "uuid", UUIDstr2uuid_bulk, false, "Coerce a string to a uuid, validating its format", args(1,3, batarg("",uuid),batarg("s",str),batarg("c",oid))),
     464             :  command("calc", "uuid", UUIDuuid2uuid, false, "", args(1,2, arg("",uuid),arg("u",uuid))),
     465             :  command("batcalc", "uuid", UUIDuuid2uuid_bulk, false, "", args(1,3, batarg("",uuid),batarg("u",uuid),batarg("c",oid))),
     466             :  command("calc", "str", UUIDuuid2str, false, "Coerce a uuid to a string type", args(1,2, arg("",str),arg("s",uuid))),
     467             :  command("batcalc", "str", UUIDuuid2str_bulk, false, "Coerce a uuid to a string type", args(1,3, batarg("",str),batarg("s",uuid),batarg("c",oid))),
     468             :  { .imp=NULL }
     469             : };
     470             : #include "mal_import.h"
     471             : #ifdef _MSC_VER
     472             : #undef read
     473             : #pragma section(".CRT$XCU",read)
     474             : #endif
     475         259 : LIB_STARTUP_FUNC(init_uuid_mal)
     476         259 : { mal_module("uuid", NULL, uuid_init_funcs); }

Generated by: LCOV version 1.14