Copies from older experiments which should not have been checked in.
[lttv.git] / ltt / branches / poly / lttv / attribute.c
1 #include "attribute.h"
2
3 inline lttv_string_id lttv_string_id_from_string(const char *s) {
4 return g_quark_from_string(s);
5 }
6
7
8 inline void lttv_string_id_release(lttv_string_id i) {}
9
10
11 inline const char *lttv_string_id_to_string(lttv_string_id i) {
12 return g_quark_to_string(i);
13 }
14
15
16 inline 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 */
22 inline 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
30 inline void lttv_key_append(lttv_key *k, lttv_string_id i) {
31 g_array_append_val(k,i);
32 }
33
34
35 inline unsigned int lttv_key_component_number(lttv_key *k) {
36 return k->len;
37 }
38
39
40 lttv_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
52 lttv_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
67 static 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
75 static 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
87 static void lttv_key_free(gpointer data)
88 {
89 lttv_key_destroy((lttv_key *)data);
90 }
91
92
93 static void lttv_attribute_value_free(gpointer data)
94 {
95 g_free(data);
96 }
97
98
99 lttv_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
117 static void lttv_attribute_key_free(gpointer k, gpointer v, gpointer data) {
118 lttv_key_free(k);
119 }
120
121
122 void 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
132 unsigned 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
140 int *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
154 lttv_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
167 double *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
180 void *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
192 void *lttv_attributes_get_pointer(lttv_attributes *a, lttv_key *k)
193 {
194 return g_hash_table_lookup(a->pointers,k);
195 }
196
197 void 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
205 void 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
234 typedef struct _lttv_attribute_fill_position {
235 unsigned i;
236 lttv_attribute_type t;
237 lttv_attribute *a;
238 } lttv_attribute_fill_position;
239
240
241 static 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
261 lttv_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
283 lttv_attribute *lttv_attribute_array_destroy(lttv_attribute *a) {
284 g_free(a);
285 }
286
287
288 void 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
298 int 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
314
315 typedef struct _select_data {
316 lttv_attributes *a;
317 lttv_key *k;
318 void *user_data;
319 lttv_key_select select;
320 } select_data;
321
322 static void select_integer(void *key, void *value, void *user_data);
323 static void select_double(void *key, void *value, void *user_data);
324 static void select_time(void *key, void *value, void *user_data);
325 static void select_pointer(void *key, void *value, void *user_data);
326
327 lttv_attributes *lttv_attributes_select(lttv_attributes *a, lttv_key_select f,
328 void *user_data)
329 {
330 select_data *d;
331
332 d = g_new(select_data, 1);
333 d->a = lttv_attributes_new();
334 d->k = lttv_key_new();
335 d->user_data = user_data;
336 d->select = f;
337
338 g_hash_table_foreach(a->ints,select_integer, d);
339 g_hash_table_foreach(a->doubles,select_double, d);
340 g_hash_table_foreach(a->times,select_time, d);
341 g_hash_table_foreach(a->pointers,select_pointer, d);
342 }
343
344 int lttv_key_select_spec(lttv_key *in, lttv_key *out, void *user_data)
345 {
346 lttv_key_select_spec_data *d = (lttv_key_select_spec_data *)user_data;
347 int i;
348
349 /* not defined yet */
350 /* lttv_key_set_size(out, 0); */
351
352 for(i = 0 ; i < d->length ; i++) {
353 switch(d->spec[i]) {
354 case LTTV_KEEP:
355 break;
356
357 case LTTV_KEEP_EQUAL:
358 break;
359
360 case LTTV_KEEP_SMALLER:
361 break;
362
363 case LTTV_KEEP_GREATER:
364 break;
365
366 case LTTV_IGNORE:
367 break;
368
369 }
370 }
371
372 return 1;
373 }
374
375 static void select_integer(void *key, void *value, void *user_data)
376 {
377 lttv_key *k = (lttv_key *)key;
378 int *pi = (int *)value;
379 select_data *d = (select_data *)user_data;
380
381 if(d->select(k,d->k,d->user_data)) {
382 *(lttv_attributes_get_integer(d->a,d->k)) += *pi;
383 }
384 }
385
386 static void select_double(void *key, void *value, void *user_data)
387 {
388 lttv_key *k = (lttv_key *)key;
389 double *pf = (double *)value;
390 select_data *d = (select_data *)user_data;
391
392 if(d->select(k,d->k,d->user_data)) {
393 *(lttv_attributes_get_double(d->a,d->k)) += *pf;
394 }
395 }
396
397 static void select_time(void *key, void *value, void *user_data)
398 {
399 lttv_key *k = (lttv_key *)key;
400 lttv_time *ptSum, *pt = (lttv_time *)value;
401 select_data *d = (select_data *)user_data;
402
403 if(d->select(k,d->k,d->user_data)) {
404 ptSum = lttv_attributes_get_time(d->a,d->k);
405 ptSum->tv_sec += pt->tv_sec;
406 ptSum->tv_nsec += pt->tv_nsec;
407 }
408 }
409
410 static void select_pointer(void *key, void *value, void *user_data)
411 {
412 lttv_key *k = (lttv_key *)key;
413 select_data *d = (select_data *)user_data;
414
415 if(d->select(k,d->k,d->user_data)) {
416 lttv_attributes_set_pointer(d->a,d->k,value);
417 }
418 }
419
420
421
422
423
This page took 0.037707 seconds and 5 git commands to generate.