compile fixes
[lttv.git] / ltt / branches / poly / lttv / attribute.c
CommitLineData
fcdf0ec2 1#include <lttv/attribute.h>
f32847a1 2
3inline lttv_string_id lttv_string_id_from_string(const char *s) {
4 return g_quark_from_string(s);
5}
6
7
8inline void lttv_string_id_release(lttv_string_id i) {}
9
10
11inline const char *lttv_string_id_to_string(lttv_string_id i) {
12 return g_quark_to_string(i);
13}
14
15
16inline lttv_key *lttv_key_new() {
17 return g_array_new(FALSE, FALSE, sizeof(lttv_string_id));
18}
19
20/* Changed this function to destroy the element also, caused memory leak? */
21/* Mathieu Desnoyers */
22inline void lttv_key_destroy(lttv_key *k) {
23 g_array_free(k, TRUE);
24}
25
26
27#define _lttv_key_index(k,i) g_array_index(k, lttv_string_id, i)
28
29
30inline void lttv_key_append(lttv_key *k, lttv_string_id i) {
31 g_array_append_val(k,i);
32}
33
34
35inline unsigned int lttv_key_component_number(lttv_key *k) {
36 return k->len;
37}
38
39
40lttv_key *lttv_key_copy(lttv_key *k) {
41 lttv_key *nk;
42 int i;
43
44 nk = lttv_key_new();
45 for(i = 0 ; i < k->len ; i++) lttv_key_append(nk,lttv_key_index(k,i));
46 return nk;
47}
48
49/* It is also possible to create a key directly from a pathname,
50 key components separated by /, (e.g., "/hooks/options/before"). */
51
52lttv_key *lttv_key_new_pathname(const char *p) {
53 char **v, **cursor;
54 lttv_key *k;
55
56 v = cursor = g_strsplit(p, "/", -1);
57 k = lttv_key_new();
58
59 while(*cursor != NULL) {
60 lttv_key_append(k, lttv_string_id_from_string(*cursor));
61 cursor++;
62 }
63 g_strfreev(v);
64 return k;
65}
66
67static guint lttv_key_hash(gconstpointer key) {
68 lttv_key * k = (lttv_key *)key;
69 guint h = 0;
70 int i;
71 for(i = 0 ; i < k->len ; i++) h = h ^ lttv_key_index(k,i);
72 return h;
73}
74
75static gboolean lttv_key_equal(gconstpointer key1,gconstpointer key2) {
76 lttv_key * k1 = (lttv_key *)key1;
77 lttv_key * k2 = (lttv_key *)key2;
78 int i;
79
80 if(k1->len != k2->len) return FALSE;
81 for(i = 0 ; i < k1->len ; i++)
82 if(lttv_key_index(k1,i) != lttv_key_index(k2,i)) return FALSE;
83 return TRUE;
84}
85
86
87static void lttv_key_free(gpointer data)
88{
89 lttv_key_destroy((lttv_key *)data);
90}
91
92
93static void lttv_attribute_value_free(gpointer data)
94{
95 g_free(data);
96}
97
98
99lttv_attributes *lttv_attributes_new() {
100 lttv_attributes *a;
101
102 a = g_new(lttv_attributes, 1);
103 a->ints = g_hash_table_new_full(lttv_key_hash, lttv_key_equal,
104 lttv_key_free, lttv_attribute_value_free);
105 a->times = g_hash_table_new_full(lttv_key_hash, lttv_key_equal,
106 lttv_key_free, lttv_attribute_value_free);
107 a->doubles = g_hash_table_new_full(lttv_key_hash, lttv_key_equal,
108 lttv_key_free, lttv_attribute_value_free);
109 a->pointers = g_hash_table_new(lttv_key_hash, lttv_key_equal);
110
111 return a;
112}
113
114
115/* Free the hash table containing the stats and all the contained keys/vals */
116
117static void lttv_attribute_key_free(gpointer k, gpointer v, gpointer data) {
118 lttv_key_free(k);
119}
120
121
122void lttv_attributes_destroy(lttv_attributes *a) {
123 g_hash_table_destroy(a->ints);
124 g_hash_table_destroy(a->times);
125 g_hash_table_destroy(a->doubles);
126
127 g_hash_table_foreach(a->pointers, lttv_attribute_key_free, NULL);
128 g_hash_table_destroy(a->pointers);
129 g_free(a);
130}
131
132unsigned int lttv_attributes_number(lttv_attributes *a) {
133 return g_hash_table_size(a->ints) + g_hash_table_size(a->times) +
134 g_hash_table_size(a->doubles) + g_hash_table_size(a->pointers);
135}
136
137
138/* If it is a new entry, insert it in the hash table, and set it to 0 */
139
140int *lttv_attributes_get_integer(lttv_attributes *a, lttv_key *k)
141{
142 gpointer found;
143
144 found = g_hash_table_lookup(a->ints, k);
145 if(found == NULL) {
146 found = g_new(gint, 1);
147 *(gint *)found = 0;
148 g_hash_table_insert(a->ints, lttv_key_copy(k), found);
149 }
150 return found;
151}
152
153
154lttv_time *lttv_attributes_get_time(lttv_attributes *a, lttv_key *k)
155{
156 gpointer found;
157
158 found = g_hash_table_lookup(a->times, k);
159 if(found == NULL) {
160 found = g_new0(lttv_time, 1);
161 /* *(lttv_time *)found = ZeroTime; */
162 g_hash_table_insert(a->times, lttv_key_copy(k), found);
163 }
164 return found;
165}
166
167double *lttv_attributes_get_double(lttv_attributes *a, lttv_key *k)
168{
169 gpointer found;
170
171 found = g_hash_table_lookup(a->doubles,k);
172 if(found == NULL) {
173 found = g_new(double,1);
174 *(double *)found = 0;
175 g_hash_table_insert(a->doubles, lttv_key_copy(k),found);
176 }
177 return found;
178}
179
180void *lttv_attributes_get_pointer_pathname(lttv_attributes *a, char *pn)
181{
182 lttv_key *key;
183 void *p;
184
185 key = lttv_key_new_pathname(pn);
186 p = lttv_attributes_get_pointer(a, key);
187 lttv_key_destroy(key);
188
189 return p;
190}
191
192void *lttv_attributes_get_pointer(lttv_attributes *a, lttv_key *k)
193{
194 return g_hash_table_lookup(a->pointers,k);
195}
196
197void lttv_attributes_set_pointer_pathname(lttv_attributes *a,char *pn,void *p)
198{
199 lttv_key *key = lttv_key_new_pathname(pn);
200
201 lttv_attributes_set_pointer(a, key, p);
202 lttv_key_destroy(key);
203}
204
205void lttv_attributes_set_pointer(lttv_attributes *a, lttv_key *k, void *p) {
206 lttv_key * oldk;
207 void *oldv;
208
209 if(g_hash_table_lookup_extended(a->pointers, k, (gpointer)oldk, &oldv)) {
210 if(p == NULL) {
211 g_hash_table_remove(a->pointers,k);
212 }
213 else {
214 g_hash_table_insert(a->pointers,oldk,p);
215 }
216 }
217 else {
218 if(p == NULL) return;
219 g_hash_table_insert(a->pointers,lttv_key_copy(k),p);
220 }
221}
222
223
224/* Sometimes the attributes must be accessed in bulk, sorted in different
225 ways. For this purpose they may be converted to arrays and sorted
226 multiple times. The keys used in the array belong to the lttv_attributes
227 object from which the array was obtained and are freed when it is
228 destroyed. Each element in the array is an lttv_attribute, a structure
229 containing the key, the value type, and a union containing a value of
230 that type. Multiple attributes with equal keys may be possible in some
231 implementations if their type differs. */
232
233
234typedef struct _lttv_attribute_fill_position {
235 unsigned i;
236 lttv_attribute_type t;
237 lttv_attribute *a;
238} lttv_attribute_fill_position;
239
240
241static void lttv_attribute_fill(void *key, void *value, void *user_data) {
242 lttv_attribute_fill_position * p = (lttv_attribute_fill_position *)user_data;
243 lttv_attribute *a = p->a + p->i;
244
245 a->key = (lttv_key *)key;
246 a->t = p->t;
247 switch(p->t) {
248 case LTTV_INTEGER:
249 a->v.i = *((int *)value);
250 case LTTV_TIME:
251 a->v.t = *((lttv_time *)value);
252 case LTTV_DOUBLE:
253 a->v.d = *((double *)value);
254 case LTTV_POINTER:
255 a->v.p = value;
256 }
257 p->i++;
258}
259
260
261lttv_attribute *lttv_attributes_array_get(lttv_attributes *a) {
262 unsigned size;
263 lttv_attribute *v;
264 lttv_attribute_fill_position p;
265
266 size = lttv_attributes_number(a);
267 v = g_new(lttv_attribute,size);
268
269 p.a = v;
270 p.i = 0;
271 p.t = LTTV_INTEGER;
272 g_hash_table_foreach(a->ints, lttv_attribute_fill, &p);
273 p.t = LTTV_TIME;
274 g_hash_table_foreach(a->times, lttv_attribute_fill, &p);
275 p.t = LTTV_DOUBLE;
276 g_hash_table_foreach(a->doubles, lttv_attribute_fill, &p);
277 p.t = LTTV_POINTER;
278 g_hash_table_foreach(a->pointers, lttv_attribute_fill, &p);
279 return v;
280}
281
282
283lttv_attribute *lttv_attribute_array_destroy(lttv_attribute *a) {
284 g_free(a);
285}
286
287
288void lttv_attribute_array_sort(lttv_attribute *a,
289 unsigned size, lttv_key_compare f,
290 void *compare_data)
291{
292
293 g_qsort_with_data(a, size, sizeof(lttv_attribute), f,
294 compare_data);
295}
296
297
298int lttv_key_compare_priority(lttv_key *a, lttv_key *b, void *compare_data)
299{
300 int i, res;
301 int *priority = (int *)compare_data;
302
303 g_assert(a->len == b->len);
304
305 for(i = 0 ; i < a->len ; i++)
306 {
307 res = strcmp(lttv_string_id_to_string(lttv_key_index(a,priority[i])),
308 lttv_string_id_to_string(lttv_key_index(a,priority[i])));
309 if(res != 0) return res;
310 }
311 return 0;
312}
313
f32847a1 314typedef struct _select_data {
315 lttv_attributes *a;
316 lttv_key *k;
317 void *user_data;
318 lttv_key_select select;
319} select_data;
320
321static void select_integer(void *key, void *value, void *user_data);
322static void select_double(void *key, void *value, void *user_data);
323static void select_time(void *key, void *value, void *user_data);
324static void select_pointer(void *key, void *value, void *user_data);
325
326lttv_attributes *lttv_attributes_select(lttv_attributes *a, lttv_key_select f,
327 void *user_data)
328{
329 select_data *d;
330
331 d = g_new(select_data, 1);
332 d->a = lttv_attributes_new();
333 d->k = lttv_key_new();
334 d->user_data = user_data;
335 d->select = f;
336
337 g_hash_table_foreach(a->ints,select_integer, d);
338 g_hash_table_foreach(a->doubles,select_double, d);
339 g_hash_table_foreach(a->times,select_time, d);
340 g_hash_table_foreach(a->pointers,select_pointer, d);
341}
342
343int lttv_key_select_spec(lttv_key *in, lttv_key *out, void *user_data)
344{
345 lttv_key_select_spec_data *d = (lttv_key_select_spec_data *)user_data;
346 int i;
347
348 /* not defined yet */
349 /* lttv_key_set_size(out, 0); */
350
351 for(i = 0 ; i < d->length ; i++) {
352 switch(d->spec[i]) {
353 case LTTV_KEEP:
354 break;
355
356 case LTTV_KEEP_EQUAL:
357 break;
358
359 case LTTV_KEEP_SMALLER:
360 break;
361
362 case LTTV_KEEP_GREATER:
363 break;
364
365 case LTTV_IGNORE:
366 break;
367
368 }
369 }
370
371 return 1;
372}
373
374static void select_integer(void *key, void *value, void *user_data)
375{
376 lttv_key *k = (lttv_key *)key;
377 int *pi = (int *)value;
378 select_data *d = (select_data *)user_data;
379
380 if(d->select(k,d->k,d->user_data)) {
381 *(lttv_attributes_get_integer(d->a,d->k)) += *pi;
382 }
383}
384
385static void select_double(void *key, void *value, void *user_data)
386{
387 lttv_key *k = (lttv_key *)key;
388 double *pf = (double *)value;
389 select_data *d = (select_data *)user_data;
390
391 if(d->select(k,d->k,d->user_data)) {
392 *(lttv_attributes_get_double(d->a,d->k)) += *pf;
393 }
394}
395
396static void select_time(void *key, void *value, void *user_data)
397{
398 lttv_key *k = (lttv_key *)key;
399 lttv_time *ptSum, *pt = (lttv_time *)value;
400 select_data *d = (select_data *)user_data;
401
402 if(d->select(k,d->k,d->user_data)) {
403 ptSum = lttv_attributes_get_time(d->a,d->k);
404 ptSum->tv_sec += pt->tv_sec;
405 ptSum->tv_nsec += pt->tv_nsec;
406 }
407}
408
409static void select_pointer(void *key, void *value, void *user_data)
410{
411 lttv_key *k = (lttv_key *)key;
412 select_data *d = (select_data *)user_data;
413
414 if(d->select(k,d->k,d->user_data)) {
415 lttv_attributes_set_pointer(d->a,d->k,value);
416 }
417}
418
419
420
421
422
This page took 0.037231 seconds and 4 git commands to generate.