1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
//------------------------------------------------------------------------------
// GxB_Type_new: create a new user-defined type
//------------------------------------------------------------------------------
// SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2022, All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//------------------------------------------------------------------------------
// GxB_Type_new is like GrB_Type_new, except that it gives the user application
// a mechanism for providing a unique name of the type and the C definition of
// the type. Both are provided as null-terminated strings.
// When the name of the user type is known, it can be returned to the user
// application when querying the type of a GrB_Matrix, GrB_Vector, GrB_Scalar,
// or a serialized blob.
// If GrB_Type_new is used in SuiteSparse:GraphBLAS in its macro form, as
// GrB_Type_new (&t, sizeof (myctype)), then the type_name is extracted as the
// string "myctype". This type_name can then be returnd by
// GxB_Matrix_type_name, GxB_deserialize_type_name, etc.
// This is not used for built-in types. Those are created statically.
// Example:
// GxB_Type_new (&MyQtype, sizeof (myquaternion), "myquaternion",
// "typedef struct { float x [4][4] ; int color ; } myquaternion ;") ;
// The type_name and type_defn are optional and may by NULL, but they are
// required for the JIT.
#include "GB.h"
GrB_Info GxB_Type_new
(
GrB_Type *type, // handle of user type to create
size_t sizeof_ctype, // size of the user type
const char *type_name, // name of the user type, or "sizeof (ctype)"
const char *type_defn // typedef of the C type (any length)
)
{
//--------------------------------------------------------------------------
// check inputs
//--------------------------------------------------------------------------
GB_WHERE1 ("GxB_Type_new (&type, sizeof (ctype), type_name, type_defn)") ;
GB_RETURN_IF_NULL (type) ;
(*type) = NULL ;
#if ( ! GB_HAS_VLA )
{
// Microsoft Visual Studio does not support VLAs allocating
// automatically on the stack. These arrays are used for scalar values
// for a given type. If VLA is not supported, user-defined types can
// be no larger than GB_VLA_MAXSIZE.
if (sizeof_ctype > GB_VLA_MAXSIZE)
{
return (GrB_INVALID_VALUE) ;
}
}
#endif
//--------------------------------------------------------------------------
// create the type
//--------------------------------------------------------------------------
// allocate the type
size_t header_size ;
GrB_Type t = GB_MALLOC (1, struct GB_Type_opaque, &header_size) ;
if (t == NULL)
{
// out of memory
return (GrB_OUT_OF_MEMORY) ;
}
// initialize the type
t->header_size = header_size ;
t->size = GB_IMAX (sizeof_ctype, 1) ;
t->code = GB_UDT_code ; // user-defined type
memset (t->name, 0, GxB_MAX_NAME_LEN) ; // no name yet
t->defn = NULL ; // no definition yet
t->defn_size = 0 ;
//--------------------------------------------------------------------------
// get the name: as a type_name or "sizeof (type_name)"
//--------------------------------------------------------------------------
if (type_name != NULL)
{
// copy the type_name into the working name
char working [GxB_MAX_NAME_LEN] ;
memset (working, 0, GxB_MAX_NAME_LEN) ;
strncpy (working, type_name, GxB_MAX_NAME_LEN-1) ;
// look for "sizeof" in the name
char *p = NULL ;
p = strstr (working, "sizeof") ;
if (p != NULL)
{
// "sizeof" appears in the input string, advance past it
p += 6 ;
// find leading "(" if it appears, and advance to one char past it
char *p2 = strstr (p, "(") ;
if (p2 != NULL) p = p2 + 1 ;
// find trailing ")" if it appears, and delete it
p2 = strstr (p, ")") ;
if (p2 != NULL) *p2 = '\0' ;
// p now contains the final name, copy it to the output name
strncpy (t->name, p, GxB_MAX_NAME_LEN-1) ;
}
else
{
// "sizeof" does not appear, take the input type_name as-is
memcpy (t->name, working, GxB_MAX_NAME_LEN) ;
}
}
else
{
// no type name, so give it a generic name, with the typesize only
snprintf (t->name, GxB_MAX_NAME_LEN-1, "user_type_of_size_" GBu,
(uint64_t) sizeof_ctype) ;
}
// ensure t->name is null-terminated
t->name [GxB_MAX_NAME_LEN-1] = '\0' ;
//--------------------------------------------------------------------------
// get the typedef, if present
//--------------------------------------------------------------------------
if (type_defn != NULL)
{
// determine the string length of the typedef
size_t len = strlen (type_defn) ;
// allocate space for the typedef
t->defn = GB_MALLOC (len+1, char, &(t->defn_size)) ;
if (t->defn == NULL)
{
// out of memory
GB_FREE (&t, header_size) ;
return (GrB_OUT_OF_MEMORY) ;
}
// copy the typedef into the new type
memcpy (t->defn, type_defn, len+1) ;
}
//--------------------------------------------------------------------------
// return result
//--------------------------------------------------------------------------
t->magic = GB_MAGIC ;
(*type) = t ;
ASSERT_TYPE_OK (t, "new user-defined type", GB0) ;
return (GrB_SUCCESS) ;
}
//------------------------------------------------------------------------------
// GB_Type_new: create a new user-defined type (historical)
//------------------------------------------------------------------------------
// This method was only accessible via the GrB_Type_new macro in v5.1.x and
// earlier. The GrB_Type_new macro in v5.2.x and later calls GxB_Type_new.
GrB_Info GB_Type_new // create a new GraphBLAS type
(
GrB_Type *type, // handle of user type to create
size_t sizeof_ctype, // size = sizeof (ctype) of the C type
const char *name // name of the type
)
{
return (GxB_Type_new (type, sizeof_ctype, name, NULL)) ;
}
|