3 inline lttv_string_id
lttv_string_id_from_string(const char *s
) {
4 return g_quark_from_string(s
);
8 inline void lttv_string_id_release(lttv_string_id i
) {}
11 inline const char *lttv_string_id_to_string(lttv_string_id i
) {
12 return g_quark_to_string(i
);
16 inline lttv_key
*lttv_key_new() {
17 return g_array_new(FALSE
, FALSE
, sizeof(lttv_string_id
));
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
);
27 #define _lttv_key_index(k,i) g_array_index(k, lttv_string_id, i)
30 inline void lttv_key_append(lttv_key
*k
, lttv_string_id i
) {
31 g_array_append_val(k
,i
);
35 inline unsigned int lttv_key_component_number(lttv_key
*k
) {
40 lttv_key
*lttv_key_copy(lttv_key
*k
) {
45 for(i
= 0 ; i
< k
->len
; i
++) lttv_key_append(nk
,lttv_key_index(k
,i
));
49 /* It is also possible to create a key directly from a pathname,
50 key components separated by /, (e.g., "/hooks/options/before"). */
52 lttv_key
*lttv_key_new_pathname(const char *p
) {
56 v
= cursor
= g_strsplit(p
, "/", -1);
59 while(*cursor
!= NULL
) {
60 lttv_key_append(k
, lttv_string_id_from_string(*cursor
));
67 static guint
lttv_key_hash(gconstpointer key
) {
68 lttv_key
* k
= (lttv_key
*)key
;
71 for(i
= 0 ; i
< k
->len
; i
++) h
= h
^ lttv_key_index(k
,i
);
75 static gboolean
lttv_key_equal(gconstpointer key1
,gconstpointer key2
) {
76 lttv_key
* k1
= (lttv_key
*)key1
;
77 lttv_key
* k2
= (lttv_key
*)key2
;
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
;
87 static void lttv_key_free(gpointer data
)
89 lttv_key_destroy((lttv_key
*)data
);
93 static void lttv_attribute_value_free(gpointer data
)
99 lttv_attributes
*lttv_attributes_new() {
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
);
115 /* Free the hash table containing the stats and all the contained keys/vals */
117 static void lttv_attribute_key_free(gpointer k
, gpointer v
, gpointer data
) {
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
);
127 g_hash_table_foreach(a
->pointers
, lttv_attribute_key_free
, NULL
);
128 g_hash_table_destroy(a
->pointers
);
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
);
138 /* If it is a new entry, insert it in the hash table, and set it to 0 */
140 int *lttv_attributes_get_integer(lttv_attributes
*a
, lttv_key
*k
)
144 found
= g_hash_table_lookup(a
->ints
, k
);
146 found
= g_new(gint
, 1);
148 g_hash_table_insert(a
->ints
, lttv_key_copy(k
), found
);
154 lttv_time
*lttv_attributes_get_time(lttv_attributes
*a
, lttv_key
*k
)
158 found
= g_hash_table_lookup(a
->times
, k
);
160 found
= g_new0(lttv_time
, 1);
161 /* *(lttv_time *)found = ZeroTime; */
162 g_hash_table_insert(a
->times
, lttv_key_copy(k
), found
);
167 double *lttv_attributes_get_double(lttv_attributes
*a
, lttv_key
*k
)
171 found
= g_hash_table_lookup(a
->doubles
,k
);
173 found
= g_new(double,1);
174 *(double *)found
= 0;
175 g_hash_table_insert(a
->doubles
, lttv_key_copy(k
),found
);
180 void *lttv_attributes_get_pointer_pathname(lttv_attributes
*a
, char *pn
)
185 key
= lttv_key_new_pathname(pn
);
186 p
= lttv_attributes_get_pointer(a
, key
);
187 lttv_key_destroy(key
);
192 void *lttv_attributes_get_pointer(lttv_attributes
*a
, lttv_key
*k
)
194 return g_hash_table_lookup(a
->pointers
,k
);
197 void lttv_attributes_set_pointer_pathname(lttv_attributes
*a
,char *pn
,void *p
)
199 lttv_key
*key
= lttv_key_new_pathname(pn
);
201 lttv_attributes_set_pointer(a
, key
, p
);
202 lttv_key_destroy(key
);
205 void lttv_attributes_set_pointer(lttv_attributes
*a
, lttv_key
*k
, void *p
) {
209 if(g_hash_table_lookup_extended(a
->pointers
, k
, (gpointer
)oldk
, &oldv
)) {
211 g_hash_table_remove(a
->pointers
,k
);
214 g_hash_table_insert(a
->pointers
,oldk
,p
);
218 if(p
== NULL
) return;
219 g_hash_table_insert(a
->pointers
,lttv_key_copy(k
),p
);
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. */
234 typedef struct _lttv_attribute_fill_position
{
236 lttv_attribute_type t
;
238 } lttv_attribute_fill_position
;
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
;
245 a
->key
= (lttv_key
*)key
;
249 a
->v
.i
= *((int *)value
);
251 a
->v
.t
= *((lttv_time
*)value
);
253 a
->v
.d
= *((double *)value
);
261 lttv_attribute
*lttv_attributes_array_get(lttv_attributes
*a
) {
264 lttv_attribute_fill_position p
;
266 size
= lttv_attributes_number(a
);
267 v
= g_new(lttv_attribute
,size
);
272 g_hash_table_foreach(a
->ints
, lttv_attribute_fill
, &p
);
274 g_hash_table_foreach(a
->times
, lttv_attribute_fill
, &p
);
276 g_hash_table_foreach(a
->doubles
, lttv_attribute_fill
, &p
);
278 g_hash_table_foreach(a
->pointers
, lttv_attribute_fill
, &p
);
283 lttv_attribute
*lttv_attribute_array_destroy(lttv_attribute
*a
) {
288 void lttv_attribute_array_sort(lttv_attribute
*a
,
289 unsigned size
, lttv_key_compare f
,
293 g_qsort_with_data(a
, size
, sizeof(lttv_attribute
), f
,
298 int lttv_key_compare_priority(lttv_key
*a
, lttv_key
*b
, void *compare_data
)
301 int *priority
= (int *)compare_data
;
303 g_assert(a
->len
== b
->len
);
305 for(i
= 0 ; i
< a
->len
; i
++)
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
;
315 typedef struct _select_data
{
319 lttv_key_select select
;
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
);
327 lttv_attributes
*lttv_attributes_select(lttv_attributes
*a
, lttv_key_select f
,
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
;
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
);
344 int lttv_key_select_spec(lttv_key
*in
, lttv_key
*out
, void *user_data
)
346 lttv_key_select_spec_data
*d
= (lttv_key_select_spec_data
*)user_data
;
349 /* not defined yet */
350 /* lttv_key_set_size(out, 0); */
352 for(i
= 0 ; i
< d
->length
; i
++) {
357 case LTTV_KEEP_EQUAL
:
360 case LTTV_KEEP_SMALLER
:
363 case LTTV_KEEP_GREATER
:
375 static void select_integer(void *key
, void *value
, void *user_data
)
377 lttv_key
*k
= (lttv_key
*)key
;
378 int *pi
= (int *)value
;
379 select_data
*d
= (select_data
*)user_data
;
381 if(d
->select(k
,d
->k
,d
->user_data
)) {
382 *(lttv_attributes_get_integer(d
->a
,d
->k
)) += *pi
;
386 static void select_double(void *key
, void *value
, void *user_data
)
388 lttv_key
*k
= (lttv_key
*)key
;
389 double *pf
= (double *)value
;
390 select_data
*d
= (select_data
*)user_data
;
392 if(d
->select(k
,d
->k
,d
->user_data
)) {
393 *(lttv_attributes_get_double(d
->a
,d
->k
)) += *pf
;
397 static void select_time(void *key
, void *value
, void *user_data
)
399 lttv_key
*k
= (lttv_key
*)key
;
400 lttv_time
*ptSum
, *pt
= (lttv_time
*)value
;
401 select_data
*d
= (select_data
*)user_data
;
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
;
410 static void select_pointer(void *key
, void *value
, void *user_data
)
412 lttv_key
*k
= (lttv_key
*)key
;
413 select_data
*d
= (select_data
*)user_data
;
415 if(d
->select(k
,d
->k
,d
->user_data
)) {
416 lttv_attributes_set_pointer(d
->a
,d
->k
,value
);