Commit | Line | Data |
---|---|---|
448d3cc7 MD |
1 | /* |
2 | * BabelTrace - Enumeration Type | |
3 | * | |
4 | * Copyright (c) 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
5 | * | |
6 | * This library is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU Lesser General Public | |
8 | * License as published by the Free Software Foundation; either | |
9 | * version 2.1 of the License, or (at your option) any later version. | |
10 | * | |
11 | * This library is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * Lesser General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU Lesser General Public | |
17 | * License along with this library; if not, write to the Free Software | |
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
19 | */ | |
20 | ||
21 | #include <babeltrace/compiler.h> | |
22 | #include <babeltrace/types.h> | |
23 | #include <stdint.h> | |
24 | #include <glib.h> | |
25 | ||
26 | struct enum_table { | |
27 | GHashTable *value_to_quark; /* Tuples (value, GQuark) */ | |
28 | GHashTable *quark_to_value; /* Tuples (GQuark, value) */ | |
29 | }; | |
30 | ||
31 | #if (__WORDSIZE == 32) | |
32 | GQuark enum_uint_to_quark(const struct type_class_enum *enum_class, uint64_t v) | |
33 | { | |
34 | gconstpointer q = g_hash_table_lookup(enum_class->table.value_to_quark, | |
35 | &v); | |
36 | return (GQuark) (unsigned long) q; | |
37 | } | |
38 | ||
39 | GQuark enum_int_to_quark(const struct type_class_enum *enum_class, uint64_t v) | |
40 | { | |
41 | gconstpointer q = g_hash_table_lookup(enum_class->table.value_to_quark, | |
42 | &v); | |
43 | return (GQuark) (unsigned long) q; | |
44 | } | |
45 | ||
46 | uint64_t enum_quark_to_uint(const struct type_class_enum *enum_class, | |
47 | size_t len, int byte_order, GQuark q) | |
48 | { | |
49 | gconstpointer v = g_hash_table_lookup(enum_class->table.quark_to_value, | |
50 | (gconstpointer) q); | |
51 | return *(const uint64_t *) v; | |
52 | } | |
53 | ||
54 | int64_t enum_quark_to_int(const struct type_class_enum *enum_class, | |
55 | size_t len, int byte_order, GQuark q) | |
56 | { | |
57 | gconstpointer v = g_hash_table_lookup(enum_class->table.quark_to_value, | |
58 | (gconstpointer) q); | |
59 | return *(const int64_t *) v; | |
60 | } | |
61 | ||
62 | guint enum_val_hash(gconstpointer key) | |
63 | { | |
64 | int64_t ukey = *(const int64_t *)key; | |
65 | ||
66 | return (guint)ukey ^ (guint)(ukey >> 32); | |
67 | } | |
68 | ||
69 | gboolean enum_val_equal(gconstpointer a, gconstpointer b) | |
70 | { | |
71 | int64_t ua = *(const int64_t *)a; | |
72 | int64_t ub = *(const int64_t *)b; | |
73 | ||
74 | return ua == ub; | |
75 | } | |
76 | ||
77 | void enum_val_free(void *ptr) | |
78 | { | |
79 | g_free(ptr); | |
80 | } | |
81 | ||
82 | void enum_signed_insert(struct type_class_enum *enum_class, int64_t v, GQuark q) | |
83 | { | |
84 | int64_t *valuep = g_new(int64_t, 1); | |
85 | ||
86 | g_hash_table_insert(enum_class->table>value_to_quark, valuep, | |
87 | (gpointer) (unsigned long) q); | |
88 | g_hash_table_insert(enum_class->table.quark_to_value, | |
89 | (gpointer) (unsigned long) q, | |
90 | valuep); | |
91 | } | |
92 | ||
93 | void enum_unsigned_insert(struct type_class_enum *enum_class, uint64_t v, GQuark q) | |
94 | { | |
95 | uint64_t *valuep = g_new(uint64_t, 1); | |
96 | ||
97 | g_hash_table_insert(enum_class->table.value_to_quark, valuep, | |
98 | (gpointer) (unsigned long) q); | |
99 | g_hash_table_insert(enum_class->table.quark_to_value, | |
100 | (gpointer) (unsigned long) q, | |
101 | valuep); | |
102 | } | |
103 | #else /* __WORDSIZE != 32 */ | |
104 | GQuark enum_uint_to_quark(const struct type_class_enum *enum_class, uint64_t v) | |
105 | { | |
106 | gconstpointer q = g_hash_table_lookup(enum_class->table.value_to_quark, | |
107 | (gconstpointer) v); | |
108 | return (GQuark) (unsigned long) q; | |
109 | } | |
110 | ||
111 | GQuark enum_int_to_quark(const struct type_class_enum *enum_class, uint64_t v) | |
112 | { | |
113 | gconstpointer q = g_hash_table_lookup(enum_class->table.value_to_quark, | |
114 | (gconstpointer) v); | |
115 | return (GQuark) (unsigned long) q; | |
116 | } | |
117 | ||
118 | uint64_t enum_quark_to_uint(const struct type_class_enum *enum_class, | |
119 | size_t len, int byte_order, GQuark q) | |
120 | { | |
121 | gconstpointer v = g_hash_table_lookup(enum_class->table.quark_to_value, | |
122 | (gconstpointer) (unsigned long) q); | |
123 | return *(const uint64_t *) v; | |
124 | } | |
125 | ||
126 | int64_t enum_quark_to_int(const struct type_class_enum *enum_class, | |
127 | size_t len, int byte_order, GQuark q) | |
128 | { | |
129 | gconstpointer v = g_hash_table_lookup(enum_class->table.quark_to_value, | |
130 | (gconstpointer) (unsigned long) q); | |
131 | return *(const int64_t *) v; | |
132 | } | |
133 | ||
134 | guint enum_val_hash(gconstpointer key) | |
135 | { | |
136 | return g_direct_hash(key); | |
137 | } | |
138 | ||
139 | gboolean enum_val_equal(gconstpointer a, gconstpointer b) | |
140 | { | |
141 | return g_direct_equal(a, b); | |
142 | } | |
143 | ||
144 | void enum_val_free(void *ptr) | |
145 | { | |
146 | } | |
147 | ||
148 | void enum_signed_insert(struct type_class_enum *enum_class, | |
149 | int64_t v, GQuark q) | |
150 | { | |
151 | g_hash_table_insert(enum_class->table.value_to_quark, (gpointer) v, | |
152 | (gpointer) (unsigned long) q); | |
153 | g_hash_table_insert(enum_class->table.quark_to_value, | |
154 | (gpointer) (unsigned long) q, | |
155 | valuep); | |
156 | } | |
157 | ||
158 | void enum_unsigned_insert(struct type_class_enum *enum_class, | |
159 | uint64_t v, GQuark q) | |
160 | { | |
161 | g_hash_table_insert(enum_class->table.value_to_quark, (gpointer) v, | |
162 | (gpointer) (unsigned long) q); | |
163 | g_hash_table_insert(enum_class->table.quark_to_value, | |
164 | (gpointer) (unsigned long) q, | |
165 | valuep); | |
166 | } | |
167 | #endif /* __WORDSIZE != 32 */ | |
168 | ||
169 | size_t enum_copy(unsigned char *dest, const struct format *fdest, | |
170 | const unsigned char *src, const struct format *fsrc, | |
171 | const struct type_class *type_class) | |
172 | { | |
173 | struct type_class_enum *enum_class = | |
174 | container_of(type_class, struct type_class_enum, p); | |
7fe00194 | 175 | struct type_class_integer *int_class = &enum_class->p; |
448d3cc7 MD |
176 | GQuark v; |
177 | ||
178 | v = fsrc->enum_read(src, enum_class) | |
179 | return fdest->enum_write(dest, enum_class, v); | |
180 | } | |
181 | ||
90b676d7 MD |
182 | void enum_type_free(struct type_class_enum *enum_class) |
183 | { | |
184 | g_hash_table_destroy(enum_class->table.value_to_quark); | |
185 | g_hash_table_destroy(enum_class->table.quark_to_value); | |
186 | g_free(enum_class); | |
187 | } | |
188 | ||
189 | static | |
190 | void _enum_type_free(struct type_class *type_class) | |
191 | { | |
192 | struct type_class_enum *enum_class = | |
193 | container_of(type_class, struct type_class_enum, p); | |
194 | enum_type_free(enum_class); | |
195 | } | |
196 | ||
448d3cc7 | 197 | struct type_class_enum *enum_type_new(const char *name, |
448d3cc7 MD |
198 | size_t len, int byte_order, |
199 | int signedness, | |
200 | size_t alignment) | |
201 | { | |
448d3cc7 MD |
202 | struct type_class_integer *int_class; |
203 | int ret; | |
204 | ||
7fe00194 | 205 | enum_class = g_new(struct type_class_enum, 1); |
11796b96 MD |
206 | enum_class->table.value_to_quark = g_hash_table_new(enum_val_hash, |
207 | enum_val_equal); | |
448d3cc7 MD |
208 | enum_class->table.quark_to_value = g_hash_table_new_full(g_direct_hash, |
209 | g_direct_equal, | |
210 | NULL, enum_val_free); | |
7fe00194 | 211 | int_class = &enum_class->p; |
448d3cc7 MD |
212 | int_class->p.name = g_quark_from_string(name); |
213 | int_class->p.alignment = alignment; | |
90b676d7 MD |
214 | int_class->p.copy = enum_copy; |
215 | int_class->p.free = _enum_type_free; | |
448d3cc7 MD |
216 | int_class->len = len; |
217 | int_class->byte_order = byte_order; | |
218 | int_class->signedness = signedness; | |
448d3cc7 MD |
219 | if (int_class->p.name) { |
220 | ret = register_type(&int_class->p); | |
221 | if (ret) { | |
222 | g_hash_table_destroy(enum_class->table.value_to_quark); | |
223 | g_hash_table_destroy(enum_class->table.quark_to_value); | |
224 | g_free(enum_class); | |
225 | return NULL; | |
226 | } | |
227 | } | |
228 | return enum_class; | |
229 | } |