Commit | Line | Data |
---|---|---|
448d3cc7 | 1 | /* |
ccd7e1c8 | 2 | * enum.c |
448d3cc7 | 3 | * |
ccd7e1c8 | 4 | * BabelTrace - Enumeration Type |
448d3cc7 | 5 | * |
ccd7e1c8 | 6 | * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
448d3cc7 | 7 | * |
ccd7e1c8 MD |
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
9 | * of this software and associated documentation files (the "Software"), to deal | |
10 | * in the Software without restriction, including without limitation the rights | |
11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
12 | * copies of the Software, and to permit persons to whom the Software is | |
13 | * furnished to do so, subject to the following conditions: | |
448d3cc7 | 14 | * |
ccd7e1c8 MD |
15 | * The above copyright notice and this permission notice shall be included in |
16 | * all copies or substantial portions of the Software. | |
448d3cc7 MD |
17 | */ |
18 | ||
19 | #include <babeltrace/compiler.h> | |
20 | #include <babeltrace/types.h> | |
21 | #include <stdint.h> | |
22 | #include <glib.h> | |
23 | ||
24 | struct enum_table { | |
25 | GHashTable *value_to_quark; /* Tuples (value, GQuark) */ | |
26 | GHashTable *quark_to_value; /* Tuples (GQuark, value) */ | |
27 | }; | |
28 | ||
29 | #if (__WORDSIZE == 32) | |
30 | GQuark enum_uint_to_quark(const struct type_class_enum *enum_class, uint64_t v) | |
31 | { | |
32 | gconstpointer q = g_hash_table_lookup(enum_class->table.value_to_quark, | |
33 | &v); | |
34 | return (GQuark) (unsigned long) q; | |
35 | } | |
36 | ||
37 | GQuark enum_int_to_quark(const struct type_class_enum *enum_class, uint64_t v) | |
38 | { | |
39 | gconstpointer q = g_hash_table_lookup(enum_class->table.value_to_quark, | |
40 | &v); | |
41 | return (GQuark) (unsigned long) q; | |
42 | } | |
43 | ||
44 | uint64_t enum_quark_to_uint(const struct type_class_enum *enum_class, | |
45 | size_t len, int byte_order, GQuark q) | |
46 | { | |
47 | gconstpointer v = g_hash_table_lookup(enum_class->table.quark_to_value, | |
48 | (gconstpointer) q); | |
49 | return *(const uint64_t *) v; | |
50 | } | |
51 | ||
52 | int64_t enum_quark_to_int(const struct type_class_enum *enum_class, | |
53 | size_t len, int byte_order, GQuark q) | |
54 | { | |
55 | gconstpointer v = g_hash_table_lookup(enum_class->table.quark_to_value, | |
56 | (gconstpointer) q); | |
57 | return *(const int64_t *) v; | |
58 | } | |
59 | ||
60 | guint enum_val_hash(gconstpointer key) | |
61 | { | |
62 | int64_t ukey = *(const int64_t *)key; | |
63 | ||
64 | return (guint)ukey ^ (guint)(ukey >> 32); | |
65 | } | |
66 | ||
67 | gboolean enum_val_equal(gconstpointer a, gconstpointer b) | |
68 | { | |
69 | int64_t ua = *(const int64_t *)a; | |
70 | int64_t ub = *(const int64_t *)b; | |
71 | ||
72 | return ua == ub; | |
73 | } | |
74 | ||
75 | void enum_val_free(void *ptr) | |
76 | { | |
77 | g_free(ptr); | |
78 | } | |
79 | ||
80 | void enum_signed_insert(struct type_class_enum *enum_class, int64_t v, GQuark q) | |
81 | { | |
82 | int64_t *valuep = g_new(int64_t, 1); | |
83 | ||
84 | g_hash_table_insert(enum_class->table>value_to_quark, valuep, | |
85 | (gpointer) (unsigned long) q); | |
86 | g_hash_table_insert(enum_class->table.quark_to_value, | |
87 | (gpointer) (unsigned long) q, | |
88 | valuep); | |
89 | } | |
90 | ||
91 | void enum_unsigned_insert(struct type_class_enum *enum_class, uint64_t v, GQuark q) | |
92 | { | |
93 | uint64_t *valuep = g_new(uint64_t, 1); | |
94 | ||
95 | g_hash_table_insert(enum_class->table.value_to_quark, valuep, | |
96 | (gpointer) (unsigned long) q); | |
97 | g_hash_table_insert(enum_class->table.quark_to_value, | |
98 | (gpointer) (unsigned long) q, | |
99 | valuep); | |
100 | } | |
101 | #else /* __WORDSIZE != 32 */ | |
102 | GQuark enum_uint_to_quark(const struct type_class_enum *enum_class, uint64_t v) | |
103 | { | |
104 | gconstpointer q = g_hash_table_lookup(enum_class->table.value_to_quark, | |
105 | (gconstpointer) v); | |
106 | return (GQuark) (unsigned long) q; | |
107 | } | |
108 | ||
109 | GQuark enum_int_to_quark(const struct type_class_enum *enum_class, uint64_t v) | |
110 | { | |
111 | gconstpointer q = g_hash_table_lookup(enum_class->table.value_to_quark, | |
112 | (gconstpointer) v); | |
113 | return (GQuark) (unsigned long) q; | |
114 | } | |
115 | ||
116 | uint64_t enum_quark_to_uint(const struct type_class_enum *enum_class, | |
117 | size_t len, int byte_order, GQuark q) | |
118 | { | |
119 | gconstpointer v = g_hash_table_lookup(enum_class->table.quark_to_value, | |
120 | (gconstpointer) (unsigned long) q); | |
121 | return *(const uint64_t *) v; | |
122 | } | |
123 | ||
124 | int64_t enum_quark_to_int(const struct type_class_enum *enum_class, | |
125 | size_t len, int byte_order, GQuark q) | |
126 | { | |
127 | gconstpointer v = g_hash_table_lookup(enum_class->table.quark_to_value, | |
128 | (gconstpointer) (unsigned long) q); | |
129 | return *(const int64_t *) v; | |
130 | } | |
131 | ||
132 | guint enum_val_hash(gconstpointer key) | |
133 | { | |
134 | return g_direct_hash(key); | |
135 | } | |
136 | ||
137 | gboolean enum_val_equal(gconstpointer a, gconstpointer b) | |
138 | { | |
139 | return g_direct_equal(a, b); | |
140 | } | |
141 | ||
142 | void enum_val_free(void *ptr) | |
143 | { | |
144 | } | |
145 | ||
146 | void enum_signed_insert(struct type_class_enum *enum_class, | |
147 | int64_t v, GQuark q) | |
148 | { | |
149 | g_hash_table_insert(enum_class->table.value_to_quark, (gpointer) v, | |
150 | (gpointer) (unsigned long) q); | |
151 | g_hash_table_insert(enum_class->table.quark_to_value, | |
152 | (gpointer) (unsigned long) q, | |
153 | valuep); | |
154 | } | |
155 | ||
156 | void enum_unsigned_insert(struct type_class_enum *enum_class, | |
157 | uint64_t v, GQuark q) | |
158 | { | |
159 | g_hash_table_insert(enum_class->table.value_to_quark, (gpointer) v, | |
160 | (gpointer) (unsigned long) q); | |
161 | g_hash_table_insert(enum_class->table.quark_to_value, | |
162 | (gpointer) (unsigned long) q, | |
163 | valuep); | |
164 | } | |
165 | #endif /* __WORDSIZE != 32 */ | |
166 | ||
167 | size_t enum_copy(unsigned char *dest, const struct format *fdest, | |
168 | const unsigned char *src, const struct format *fsrc, | |
169 | const struct type_class *type_class) | |
170 | { | |
171 | struct type_class_enum *enum_class = | |
172 | container_of(type_class, struct type_class_enum, p); | |
7fe00194 | 173 | struct type_class_integer *int_class = &enum_class->p; |
448d3cc7 MD |
174 | GQuark v; |
175 | ||
176 | v = fsrc->enum_read(src, enum_class) | |
177 | return fdest->enum_write(dest, enum_class, v); | |
178 | } | |
179 | ||
90b676d7 MD |
180 | void enum_type_free(struct type_class_enum *enum_class) |
181 | { | |
182 | g_hash_table_destroy(enum_class->table.value_to_quark); | |
183 | g_hash_table_destroy(enum_class->table.quark_to_value); | |
184 | g_free(enum_class); | |
185 | } | |
186 | ||
187 | static | |
188 | void _enum_type_free(struct type_class *type_class) | |
189 | { | |
190 | struct type_class_enum *enum_class = | |
191 | container_of(type_class, struct type_class_enum, p); | |
192 | enum_type_free(enum_class); | |
193 | } | |
194 | ||
448d3cc7 | 195 | struct type_class_enum *enum_type_new(const char *name, |
448d3cc7 MD |
196 | size_t len, int byte_order, |
197 | int signedness, | |
198 | size_t alignment) | |
199 | { | |
448d3cc7 MD |
200 | struct type_class_integer *int_class; |
201 | int ret; | |
202 | ||
7fe00194 | 203 | enum_class = g_new(struct type_class_enum, 1); |
11796b96 MD |
204 | enum_class->table.value_to_quark = g_hash_table_new(enum_val_hash, |
205 | enum_val_equal); | |
448d3cc7 MD |
206 | enum_class->table.quark_to_value = g_hash_table_new_full(g_direct_hash, |
207 | g_direct_equal, | |
208 | NULL, enum_val_free); | |
7fe00194 | 209 | int_class = &enum_class->p; |
448d3cc7 MD |
210 | int_class->p.name = g_quark_from_string(name); |
211 | int_class->p.alignment = alignment; | |
90b676d7 MD |
212 | int_class->p.copy = enum_copy; |
213 | int_class->p.free = _enum_type_free; | |
448d3cc7 MD |
214 | int_class->len = len; |
215 | int_class->byte_order = byte_order; | |
216 | int_class->signedness = signedness; | |
448d3cc7 MD |
217 | if (int_class->p.name) { |
218 | ret = register_type(&int_class->p); | |
219 | if (ret) { | |
220 | g_hash_table_destroy(enum_class->table.value_to_quark); | |
221 | g_hash_table_destroy(enum_class->table.quark_to_value); | |
222 | g_free(enum_class); | |
223 | return NULL; | |
224 | } | |
225 | } | |
226 | return enum_class; | |
227 | } |