forked from LLNL/Caliper
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcali_variant.h
233 lines (193 loc) · 5.11 KB
/
cali_variant.h
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/* Copyright (c) 2015-2022, Lawrence Livermore National Security, LLC.
* See top-level LICENSE file for details.
*/
#pragma once
/** \file cali_variant.h
* \brief Caliper variant type definition
*/
#include "cali_types.h"
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
/** The variant struct manages values of different types in Caliper.
* Types with fixed size (i.e., numeric types) are stored in the variant directly.
* Variable-length types (strings and blobs) are stored as unmanaged pointers.
*/
typedef struct {
/** Least significant byte encode the type.
* Top 4 bytes encode the size of variable-length types (strings and blobs).
* Remainder encodes a small hash for variable-length types for faster comparisons.
*/
uint64_t type_and_size;
/** Value in various type representations
*/
union {
uint64_t v_uint; // let largest member be the first
bool v_bool;
double v_double;
int64_t v_int;
cali_attr_type v_type;
void* unmanaged_ptr;
const void* unmanaged_const_ptr;
} value;
} cali_variant_t;
#define CALI_VARIANT_TYPE_MASK 0xFF
#define CALI_VARIANT_HASH_MASK 0xFFFFFF00
inline cali_variant_t
cali_make_empty_variant()
{
cali_variant_t v;
v.type_and_size = 0;
v.value.v_uint = 0;
return v;
}
/** \brief Test if variant is empty
*/
inline bool
cali_variant_is_empty(cali_variant_t v)
{
return 0 == v.type_and_size;
}
/** \brief Return type of a variant
*/
cali_attr_type
cali_variant_get_type(cali_variant_t v);
/** \brief Return size of the variant's value
*/
size_t
cali_variant_get_size(cali_variant_t v);
/** \brief Get a pointer to the variant's data
*/
const void*
cali_variant_get_data(const cali_variant_t* v);
/** \brief Construct variant from type, pointer, and size
*/
cali_variant_t
cali_make_variant(cali_attr_type type, const void* ptr, size_t size);
inline cali_variant_t
cali_make_variant_from_bool(bool value)
{
cali_variant_t v;
v.type_and_size = CALI_TYPE_BOOL;
v.value.v_uint = 0;
v.value.v_bool = value;
return v;
}
inline cali_variant_t
cali_make_variant_from_int(int value)
{
cali_variant_t v;
v.type_and_size = CALI_TYPE_INT;
v.value.v_int = value;
return v;
}
inline cali_variant_t
cali_make_variant_from_int64(int64_t value)
{
cali_variant_t v;
v.type_and_size = CALI_TYPE_INT;
v.value.v_int = value;
return v;
}
inline cali_variant_t
cali_make_variant_from_uint(uint64_t value)
{
cali_variant_t v;
v.type_and_size = CALI_TYPE_UINT;
v.value.v_uint = value;
return v;
}
inline cali_variant_t
cali_make_variant_from_double(double value)
{
cali_variant_t v;
v.type_and_size = CALI_TYPE_DOUBLE;
v.value.v_double = value;
return v;
}
inline cali_variant_t
cali_make_variant_from_string(const char* value)
{
size_t size = strlen(value);
uint64_t hash = 0;
const unsigned char* p = (const unsigned char*) value;
hash |= p[0];
hash <<= 8;
hash |= p[size/2];
hash <<= 8;
hash |= p[size-1];
hash <<= 8;
cali_variant_t v;
v.type_and_size = (size << 32) | hash | (CALI_TYPE_STRING & CALI_VARIANT_TYPE_MASK);
v.value.unmanaged_const_ptr = value;
return v;
}
inline cali_variant_t
cali_make_variant_from_type(cali_attr_type value)
{
cali_variant_t v;
v.type_and_size = CALI_TYPE_TYPE;
v.value.v_uint = 0;
v.value.v_type = value;
return v;
}
inline cali_variant_t
cali_make_variant_from_ptr(void* ptr)
{
cali_variant_t v;
v.type_and_size = CALI_TYPE_PTR;
v.value.unmanaged_ptr = ptr;
return v;
}
/** \brief Return the pointer stored in the variant. Only works for
* CALI_TYPE_PTR.
*/
inline void*
cali_variant_get_ptr(cali_variant_t v)
{
return v.type_and_size == CALI_TYPE_PTR ? v.value.unmanaged_ptr : NULL;
}
/** \brief Return the variant's value as integer
*/
int
cali_variant_to_int(cali_variant_t v, bool* okptr);
int64_t
cali_variant_to_int64(cali_variant_t v, bool* okptr);
uint64_t
cali_variant_to_uint(cali_variant_t v, bool* okptr);
double
cali_variant_to_double(cali_variant_t v, bool* okptr);
cali_attr_type
cali_variant_to_type(cali_variant_t v, bool* okptr);
bool
cali_variant_to_bool(cali_variant_t v, bool* okptr);
/** \brief Compare variant values.
*/
int
cali_variant_compare(cali_variant_t lhs, cali_variant_t rhs);
/** \brief Check if lhs and rhs' values are equal using a deep comparison.
* Caller must make sure that lhs' and rhs' type and size are equal.
*/
bool
_cali_variant_value_eq(cali_variant_t lhs, cali_variant_t rhs);
/** \brief Check if lhs is equal to rhs
*/
inline bool
cali_variant_eq(cali_variant_t lhs, cali_variant_t rhs)
{
return lhs.type_and_size == rhs.type_and_size ? _cali_variant_value_eq(lhs, rhs) : false;
}
/** \brief Pack variant into byte buffer
*/
size_t
cali_variant_pack(cali_variant_t v, unsigned char* buf);
/** \brief Unpack variant from byte buffer
*/
cali_variant_t
cali_variant_unpack(const unsigned char* buf, size_t* inc, bool* okptr);
#ifdef __cplusplus
} /* extern "C" */
#endif