1 //------------------------------------------------------------------------------
2 // GB_Type_new: create a new user-defined type
3 //------------------------------------------------------------------------------
4 
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
6 // SPDX-License-Identifier: Apache-2.0
7 
8 //------------------------------------------------------------------------------
9 
10 // This is not used for built-in types.  Those are created statically.
11 // Users should not call this function directly; use GrB_Type_new instead.
12 
13 #include "GB.h"
14 
GB_Type_new(GrB_Type * type,size_t sizeof_ctype,const char * name)15 GrB_Info GB_Type_new
16 (
17     GrB_Type *type,             // handle of user type to create
18     size_t sizeof_ctype,        // size of the user type
19     const char *name            // name of the type, as "sizeof (ctype)"
20 )
21 {
22 
23     //--------------------------------------------------------------------------
24     // check inputs
25     //--------------------------------------------------------------------------
26 
27     GB_WHERE1 ("GrB_Type_new (&type, sizeof (ctype))") ;
28     GB_RETURN_IF_NULL (type) ;
29     (*type) = NULL ;
30 
31     #if ( ! GB_HAS_VLA )
32 
33         // Microsoft Visual Studio does not support variable-length arrays
34         // allocating automatically on the stack.  These arrays are used for
35         // scalar values for a given type.  If VLA is not supported,
36         // user-defined types can be no larger than GB_VLA_MAXSIZE.
37 
38         if (sizeof_ctype > GB_VLA_MAXSIZE)
39         {
40             return (GrB_INVALID_VALUE) ;
41         }
42 
43     #endif
44 
45     //--------------------------------------------------------------------------
46     // create the type
47     //--------------------------------------------------------------------------
48 
49     // allocate the type
50     size_t header_size ;
51     (*type) = GB_MALLOC (1, struct GB_Type_opaque, &header_size) ;
52     if (*type == NULL)
53     {
54         // out of memory
55         return (GrB_OUT_OF_MEMORY) ;
56     }
57 
58     // initialize the type
59     GrB_Type t = *type ;
60     t->magic = GB_MAGIC ;
61     t->header_size = header_size ;
62     t->size = GB_IMAX (sizeof_ctype, 1) ;
63     t->code = GB_UDT_code ;     // user-defined type
64     t->name [0] = '\0' ;
65 
66     //--------------------------------------------------------------------------
67     // get the name
68     //--------------------------------------------------------------------------
69 
70     char input2 [GB_LEN+1] ;
71     char *p = NULL ;
72 
73     // look for "sizeof" in the input string
74     if (name != NULL)
75     {
76         strncpy (input2, name, GB_LEN) ;
77         p = strstr (input2, "sizeof") ;
78     }
79 
80     if (p != NULL)
81     {
82 
83         // "sizeof" appears in the input string, advance past it
84         p += 6 ;
85 
86         // find leading "(" if it appears, and advance to one character past it
87         char *p2 = strstr (p, "(") ;
88         if (p2 != NULL) p = p2 + 1 ;
89 
90         // find trailing ")" if it appears, and delete it
91         p2 = strstr (p, ")") ;
92         if (p2 != NULL) *p2 = '\0' ;
93 
94         // p now contains the final name, copy it to the output name
95         strncpy (t->name, p, GB_LEN-1) ;
96     }
97 
98     //--------------------------------------------------------------------------
99     // return result
100     //--------------------------------------------------------------------------
101 
102     return (GrB_SUCCESS) ;
103 }
104 
105