1 /***********************************************************************************************************************************
2 Variant Data Type
3 
4 Variants are lightweight objects in that they do not have their own memory context, instead they exist in the current context in
5 which they are instantiated. If a variant is needed outside the current memory context, the memory context must be switched to the
6 old context and then back. Below is a simplified example:
7 
8     Variant *result = NULL;    <--- is created in the current memory context (referred to as "old context" below)
9     MEM_CONTEXT_TEMP_BEGIN()   <--- begins a new temporary context
10     {
11         String *resultStr = strNewN("myNewStr"); <--- creates a string in the temporary memory context
12 
13         MEM_CONTEXT_PRIOR_BEGIN() <--- switch to old context so creation of the variant from the string is in old context
14         {
15             result = varNewUInt64(cvtZToUInt64(strZ(resultStr))); <--- recreates variant from the string in the old context.
16         }
17         MEM_CONTEXT_PRIOR_END(); <--- switch back to the temporary context
18     }
19     MEM_CONTEXT_TEMP_END(); <-- frees everything created inside this temporary memory context - i.e resultStr
20 ***********************************************************************************************************************************/
21 #ifndef COMMON_TYPE_VARIANT_H
22 #define COMMON_TYPE_VARIANT_H
23 
24 #include <stdint.h>
25 
26 /***********************************************************************************************************************************
27 Variant object
28 ***********************************************************************************************************************************/
29 typedef struct Variant Variant;
30 
31 /***********************************************************************************************************************************
32 Variant type
33 ***********************************************************************************************************************************/
34 typedef enum
35 {
36     varTypeBool,
37     varTypeInt,
38     varTypeInt64,
39     varTypeKeyValue,
40     varTypeString,
41     varTypeUInt,
42     varTypeUInt64,
43     varTypeVariantList,
44 } VariantType;
45 
46 #include "common/type/keyValue.h"
47 #include "common/type/string.h"
48 #include "common/type/variantList.h"
49 
50 /***********************************************************************************************************************************
51 Constructors
52 ***********************************************************************************************************************************/
53 Variant *varNewBool(bool data);
54 Variant *varNewInt(int data);
55 Variant *varNewInt64(int64_t data);
56 
57 // Note that the KeyValue is not duplicated because it this a heavy-weight operation. It is merely moved into the same MemContext as
58 // the Variant.
59 Variant *varNewKv(KeyValue *data);
60 
61 Variant *varNewStr(const String *data);
62 Variant *varNewStrZ(const char *data);
63 Variant *varNewUInt(unsigned int data);
64 Variant *varNewUInt64(uint64_t data);
65 Variant *varNewVarLst(const VariantList *data);
66 
67 Variant *varDup(const Variant *this);
68 
69 /***********************************************************************************************************************************
70 Getters/Setters
71 ***********************************************************************************************************************************/
72 #define VARIANT_COMMON                                                                                                             \
73     VariantType type;                                               /* Variant type */
74 
75 typedef struct VariantPub
76 {
77     VARIANT_COMMON
78 } VariantPub;
79 
80 typedef struct VariantBoolPub
81 {
82     VARIANT_COMMON
83     bool data;                                                      // Boolean data
84 } VariantBoolPub;
85 
86 typedef struct VariantIntPub
87 {
88     VARIANT_COMMON
89     int data;                                                       // Signed integer data
90 } VariantIntPub;
91 
92 typedef struct VariantInt64Pub
93 {
94     VARIANT_COMMON
95     int64_t data;                                                   // 64-bit signed integer data
96 } VariantInt64Pub;
97 
98 typedef struct VariantStringPub
99 {
100     VARIANT_COMMON
101     String *data;                                                   // String data
102 } VariantStringPub;
103 
104 typedef struct VariantUIntPub
105 {
106     VARIANT_COMMON
107     unsigned int data;                                              // Unsigned integer data
108 } VariantUIntPub;
109 
110 typedef struct VariantUInt64Pub
111 {
112     VARIANT_COMMON
113     uint64_t data;                                                  // 64-bit unsigned integer data
114 } VariantUInt64Pub;
115 
116 bool varBool(const Variant *this);
117 bool varBoolForce(const Variant *this);
118 
119 int varInt(const Variant *this);
120 int varIntForce(const Variant *this);
121 
122 int64_t varInt64(const Variant *this);
123 int64_t varInt64Force(const Variant *this);
124 
125 KeyValue *varKv(const Variant *this);
126 
127 const String *varStr(const Variant *this);
128 String *varStrForce(const Variant *this);
129 
130 unsigned int varUInt(const Variant *this);
131 unsigned int varUIntForce(const Variant *this);
132 
133 uint64_t varUInt64(const Variant *this);
134 uint64_t varUInt64Force(const Variant *this);
135 
136 VariantList *varVarLst(const Variant *this);
137 
138 // Variant type
139 __attribute__((always_inline)) static inline VariantType
varType(const Variant * const this)140 varType(const Variant *const this)
141 {
142     return THIS_PUB(Variant)->type;
143 }
144 
145 /***********************************************************************************************************************************
146 Functions
147 ***********************************************************************************************************************************/
148 // Test if Variants are equal
149 bool varEq(const Variant *this1, const Variant *this2);
150 
151 /***********************************************************************************************************************************
152 Destructor
153 ***********************************************************************************************************************************/
154 void varFree(Variant *this);
155 
156 /***********************************************************************************************************************************
157 Macros for constant variants
158 
159 Frequently used constant variants can be declared with these macros at compile time rather than dynamically at run time.
160 
161 Note that variants created in this way are declared as const so can't be modified or freed by the var*() methods.  Casting to
162 Variant * will generally result in a segfault.
163 
164 By convention all variant constant identifiers are appended with _VAR.
165 ***********************************************************************************************************************************/
166 // Create a Bool Variant constant inline from a bool
167 #define VARBOOL(dataParam)                                                                                                         \
168     ((const Variant *)&(const VariantBoolPub){.type = varTypeBool, .data = dataParam})
169 
170 // Create an Int Variant constant inline from an int
171 #define VARINT(dataParam)                                                                                                          \
172     ((const Variant *)&(const VariantIntPub){.type = varTypeInt, .data = dataParam})
173 
174 // Create an Int64 Variant constant inline from an int64_t
175 #define VARINT64(dataParam)                                                                                                        \
176     ((const Variant *)&(const VariantInt64Pub){.type = varTypeInt64, .data = dataParam})
177 
178 // Create a String Variant constant inline from any zero-terminated string
179 #define VARSTRZ(dataParam)                                                                                                         \
180     ((const Variant *)&(const VariantStringPub){.type = varTypeString, .data = (String *)STR(dataParam)})
181 
182 // Create a String Variant constant inline from a #define or inline string constant
183 #define VARSTRDEF(dataParam)                                                                                                       \
184     ((const Variant *)&(const VariantStringPub){.type = varTypeString, .data = (String *)STRDEF(dataParam)})
185 
186 // Create a String Variant constant inline from a String constant
187 #define VARSTR(dataParam)                                                                                                          \
188     ((const Variant *)&(const VariantStringPub){.type = varTypeString, .data = (String *)(dataParam)})
189 
190 // Used to declare String Variant constants that will be externed using VARIANT_DECLARE().  Must be used in a .c file.
191 #define VARIANT_STRDEF_EXTERN(name, dataParam)                                                                                     \
192     const Variant *const name = VARSTRDEF(dataParam)
193 
194 // Used to declare String Variant constants that will be local to the .c file.  Must be used in a .c file.
195 #define VARIANT_STRDEF_STATIC(name, dataParam)                                                                                     \
196     static const Variant *const name = VARSTRDEF(dataParam)
197 
198 // Create a UInt Variant constant inline from an unsigned int
199 #define VARUINT(dataParam)                                                                                                         \
200     ((const Variant *)&(const VariantUIntPub){.type = varTypeUInt, .data = dataParam})
201 
202 // Create a UInt64 Variant constant inline from a uint64_t
203 #define VARUINT64(dataParam)                                                                                                       \
204     ((const Variant *)&(const VariantUInt64Pub){.type = varTypeUInt64, .data = dataParam})
205 
206 // Used to extern String Variant constants declared with VARIANT_STRDEF_EXTERN/STATIC().  Must be used in a .h file.
207 #define VARIANT_DECLARE(name)                                                                                                      \
208     extern const Variant *const name
209 
210 /***********************************************************************************************************************************
211 Constant variants that are generally useful
212 ***********************************************************************************************************************************/
213 VARIANT_DECLARE(BOOL_FALSE_VAR);
214 VARIANT_DECLARE(BOOL_TRUE_VAR);
215 
216 /***********************************************************************************************************************************
217 Macros for function logging
218 ***********************************************************************************************************************************/
219 String *varToLog(const Variant *this);
220 
221 #define FUNCTION_LOG_VARIANT_TYPE                                                                                                  \
222     Variant *
223 #define FUNCTION_LOG_VARIANT_FORMAT(value, buffer, bufferSize)                                                                     \
224     FUNCTION_LOG_STRING_OBJECT_FORMAT(value, varToLog, buffer, bufferSize)
225 
226 #endif
227