Refine the interactions between the hooks provided by the different modules.
[lttv.git] / ltt / branches / poly / lttv / attribute.c
index b08c24da75a622ef45058263861b4b1ad3e9dd3b..6fab25dc1373605969e75bc7526a17afb0bda420 100644 (file)
+
 #include <lttv/attribute.h>
 
-inline lttv_string_id lttv_string_id_from_string(const char *s) {
-  return g_quark_from_string(s);
+typedef union _AttributeValue {
+  int dv_int;
+  unsigned dv_uint;
+  long dv_long;
+  unsigned long dv_ulong;
+  float dv_float;
+  double dv_double;
+  timespec dv_timespec;
+  gpointer dv_pointer;
+  char *dv_string;
+  gobject *dv_gobject;
+} AttributeValue;
+
+
+typedef struct _Attribute {
+  LttvAttributeName name;
+  LttvAttributeType type;
+  AttributeValue value;
+} Attribute;
+
+
+GType 
+lttv_attribute_get_type (void)
+{
+  static GType type = 0;
+  if (type == 0) {
+    static const GTypeInfo info = {
+      sizeof (LttvAttributeClass),
+      NULL,   /* base_init */
+      NULL,   /* base_finalize */
+      attribute_class_init,   /* class_init */
+      NULL,   /* class_finalize */
+      NULL,   /* class_data */
+      sizeof (LttvAttribute),
+      0,      /* n_preallocs */
+      attribute_instance_init    /* instance_init */
+    };
+
+    static const GInterfaceInfo iattribute_info = {
+      (GInterfaceInitFunc) attribute_interface_init,    /* interface_init */
+      NULL,                                       /* interface_finalize */
+      NULL                                        /* interface_data */
+    };
+
+    type = g_type_register_static (G_TYPE_OBJECT, "LttvAttributeType", &info, 
+        0);
+    g_type_add_interface_static (type, LTTV_IATTRIBUTE_TYPE, &iattribute_info);
+  }
+  return type;
 }
 
 
-inline void lttv_string_id_release(lttv_string_id i) {}
-
-
-inline const char *lttv_string_id_to_string(lttv_string_id i) {
-  return g_quark_to_string(i);
+unsigned int 
+lttv_attribute_get_number(LttvAttribute *self)
+{
+  return self->attributes->len;
 }
 
 
-inline lttv_key *lttv_key_new() {
-  return g_array_new(FALSE, FALSE, sizeof(lttv_string_id));
-}
-
-/* Changed this function to destroy the element also, caused memory leak? */
-/* Mathieu Desnoyers */
-inline void lttv_key_destroy(lttv_key *k) {
-  g_array_free(k, TRUE);
+gboolean 
+lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous)
+{
+  *homogeneous = FALSE;
+  return TRUE;
 }
 
 
-#define _lttv_key_index(k,i) g_array_index(k, lttv_string_id, i)
-
+LttvAttributeType 
+lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name, 
+    LttvAttributeValue *v)
+{
+  Attribute *a;
 
-inline void lttv_key_append(lttv_key *k, lttv_string_id i) {
-  g_array_append_val(k,i);
+  a = &g_array_index(self->attributes, Attribute, i);
+  *name = a->name;
+  *v = address_of_value(a->type, a->value);
+  return a->type;
 }
 
 
-inline unsigned int lttv_key_component_number(lttv_key *k) {
-  return k->len;
-}
+LttvAttributeType 
+lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name, 
+    LttvAttributeValue *v)
+{
+  Attribute *a;
 
+  unsigned i;
 
-lttv_key *lttv_key_copy(lttv_key *k) {
-  lttv_key *nk;
-  int i;
+  i = (unsigned)g_hash_table_lookup(self->names, (gconstpointer)name);
+  if(i == 0) return LTTV_NONE;
 
-  nk = lttv_key_new();
-  for(i = 0 ; i < k->len ; i++) lttv_key_append(nk,lttv_key_index(k,i));
-  return nk;
+  i--;
+  a = &g_array_index(self->attributes, Attribute, i);
+  *v = address_of_value(a->type, a->value);
+  return a->type;
 }
 
-/* It is also possible to create a key directly from a pathname,
-   key components separated by /, (e.g., "/hooks/options/before"). */
 
-lttv_key *lttv_key_new_pathname(const char *p) {
-  char **v, **cursor;
-  lttv_key *k;
-
-  v = cursor = g_strsplit(p, "/", -1);
-  k = lttv_key_new();
-
-  while(*cursor != NULL) {
-    lttv_key_append(k, lttv_string_id_from_string(*cursor));
-    cursor++;
-  }
-  g_strfreev(v);
-  return k;
-}
+LttvAttributeValue 
+lttv_attribute_add(LttvAttribute *self, LttvAttributeName name, 
+    LttvAttributeType t)
+{
+  unsigned i;
 
-static guint lttv_key_hash(gconstpointer key) {
-  lttv_key * k = (lttv_key *)key;
-  guint h = 0;
-  int i;
-  for(i = 0 ; i < k->len ; i++) h = h ^ lttv_key_index(k,i);
-  return h;
-}
+  Attribute a, *pa;
 
-static gboolean lttv_key_equal(gconstpointer key1,gconstpointer key2) {
-  lttv_key * k1 = (lttv_key *)key1;
-  lttv_key * k2 = (lttv_key *)key2;  
-  int i;
+  i = (unsigned)g_hash_table_lookup(self->names, (gconstpointer)name);
+  if(i != 0) g_error("duplicate entry in attribute table");
 
-  if(k1->len != k2->len) return FALSE;
-  for(i = 0 ; i < k1->len ; i++) 
-    if(lttv_key_index(k1,i) != lttv_key_index(k2,i)) return FALSE;
-  return TRUE;
+  a->name = name;
+  a->type = t;
+  a->value = init_value(t);
+  g_array_append_val(self->attributes, a);
+  i = self->attributes->len - 1;
+  pa = &g_array_index(self->attributes, Attribute, i)
+  g_hash_table_insert(self->names, (gconstpointer)name, (gconstpointer)i + 1);
+  return address_of_value(pa->value, t);
 }
 
 
-static void lttv_key_free(gpointer data)
-{
-  lttv_key_destroy((lttv_key *)data);
-}
-
+/* Remove an attribute */
 
-static void lttv_attribute_value_free(gpointer data) 
+void 
+lttv_attribute_remove(LttvAttribute *self, unsigned i)
 {
-  g_free(data);
-}
-
-
-lttv_attributes *lttv_attributes_new() {
-  lttv_attributes *a;
+  Attribute *a;
 
-  a = g_new(lttv_attributes, 1);
-  a->ints = g_hash_table_new_full(lttv_key_hash, lttv_key_equal,
-      lttv_key_free, lttv_attribute_value_free);
-  a->times = g_hash_table_new_full(lttv_key_hash, lttv_key_equal,
-      lttv_key_free, lttv_attribute_value_free);
-  a->doubles = g_hash_table_new_full(lttv_key_hash, lttv_key_equal,
-      lttv_key_free, lttv_attribute_value_free);
-  a->pointers = g_hash_table_new(lttv_key_hash, lttv_key_equal);
+  a = &g_array_index(self->attributes, Attribute, i);
 
-  return a;
-}
+  /* Remove the array element and its entry in the name index */
 
+  g_hash_table_remove(self->names, (gconspointer)a->name);
+  g_array_remove_index_fast(self->attributes, i);
 
-/* Free the hash table containing the stats and all the contained keys/vals */
+  /* The element used to replace the removed element has its index entry
+     all wrong now. Reinsert it with its new position. */
 
-static void lttv_attribute_key_free(gpointer k, gpointer v, gpointer data) {
-  lttv_key_free(k);
+  g_hash_table_remove(self->names, (gconstpointer)a->name);
+  g_hash_table_insert(self->names, (gconstpointer)a->name, i + 1);
 }
 
+void 
+lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name)
+{
+  unsigned i;
 
-void lttv_attributes_destroy(lttv_attributes *a) {
-  g_hash_table_destroy(a->ints);
-  g_hash_table_destroy(a->times);
-  g_hash_table_destroy(a->doubles);
-
-  g_hash_table_foreach(a->pointers, lttv_attribute_key_free, NULL);
-  g_hash_table_destroy(a->pointers);
-  g_free(a);
-}
+  i = (unsigned)g_hash_table_lookup(self->names, (gconstpointer)name);
+  if(i == 0) g_error("remove by name non existent attribute");
 
-unsigned int lttv_attributes_number(lttv_attributes *a) {
-  return g_hash_table_size(a->ints) + g_hash_table_size(a->times) +
-      g_hash_table_size(a->doubles) + g_hash_table_size(a->pointers);
+  lttv_attribute_remove(self, i - 1);
 }
 
+/* Create an empty iattribute object and add it as an attribute under the
+   specified name, or return an existing iattribute attribute. If an
+   attribute of that name already exists but is not a GObject supporting the
+   iattribute interface, return NULL. */
 
-/* If it is a new entry, insert it in the hash table, and set it to 0 */
-
-int *lttv_attributes_get_integer(lttv_attributes *a, lttv_key *k) 
+LttvIAttribute* 
+lttv_attribute_create_subdir(LttvAttribute *self, LttvAttributeName name)
 {
-  gpointer found;
+  unsigned i;
 
-  found = g_hash_table_lookup(a->ints, k);
-  if(found == NULL) {
-    found = g_new(gint, 1);
-    *(gint *)found = 0;
-    g_hash_table_insert(a->ints, lttv_key_copy(k), found);
-  }
-  return found;
-}
+  Attribute a;
 
+  LttvAttribute *new;
 
-lttv_time *lttv_attributes_get_time(lttv_attributes *a, lttv_key *k) 
-{
-  gpointer found;
-  
-  found = g_hash_table_lookup(a->times, k);
-  if(found == NULL) {
-    found = g_new0(lttv_time, 1);
-    /*    *(lttv_time *)found = ZeroTime; */
-    g_hash_table_insert(a->times, lttv_key_copy(k), found);
+  i = (unsigned)g_hash_table_lookup(self->names, (gconstpointer)name);
+  if(i != 0) {
+    a = g_array_index(self->attributes, Attribute, i - 1);
+    if(a->type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a->value->dv_gobject)) {
+      return LTTV_IATTRIBUTE(a->value->dv_gobject);
+    }
+    else return NULL;    
   }
-  return found;
+  new = g_object_new(LTTV_ATTRIBUTE_TYPE);
+  *(lttv_attribute_add(self, name, LTTV_GOBJECT)->v_gobject) = new;
+  return new;
 }
 
-double *lttv_attributes_get_double(lttv_attributes *a, lttv_key *k) 
+gboolean 
+lttv_attribute_find(LttvAttribute *self, LttvAttributeName name, 
+    LttvAttributeType t, LttvAttributeValue *v)
 {
-  gpointer found;
-
-  found = g_hash_table_lookup(a->doubles,k);
-  if(found == NULL) {
-    found = g_new(double,1);
-    *(double *)found = 0;
-    g_hash_table_insert(a->doubles, lttv_key_copy(k),found);
-  }
-  return found;
-}
+  unsigned i;
 
-void *lttv_attributes_get_pointer_pathname(lttv_attributes *a, char *pn) 
-{
-  lttv_key *key;
-  void *p;
+  Attribute *a;
 
-  key = lttv_key_new_pathname(pn);
-  p = lttv_attributes_get_pointer(a, key);
-  lttv_key_destroy(key);
+  i = (unsigned)g_hash_table_lookup(self->names, (gconstpointer)name);
+  if(i != 0) {
+    a = &g_array_index(self->attributes, Attribute, i - 1);
+    if(a->type != t) return FALSE;
+    *v = address_of_value(a->value, t);
+    return TRUE;
+  }
 
-  return p;
+  *v = lttv_attribute_add(self, name, t);
+  return TRUE;
 }
 
-void *lttv_attributes_get_pointer(lttv_attributes *a, lttv_key *k) 
-{
-  return g_hash_table_lookup(a->pointers,k);
-}
 
-void lttv_attributes_set_pointer_pathname(lttv_attributes *a,char *pn,void *p)
+static void
+attribute_interface_init (gpointer g_iface, gpointer iface_data)
 {
-  lttv_key *key = lttv_key_new_pathname(pn);
-  
-  lttv_attributes_set_pointer(a, key, p);
-  lttv_key_destroy(key);
-}
+  LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface;
 
-void lttv_attributes_set_pointer(lttv_attributes *a, lttv_key *k, void *p) {
-  lttv_key * oldk;
-  void *oldv;
+  klass->get_number = (unsigned int (*) (LttvIAttribute *self)) 
+      lttv_attribute_get_number;
 
-  if(g_hash_table_lookup_extended(a->pointers, k, (gpointer)oldk, &oldv)) {
-    if(p == NULL) {
-      g_hash_table_remove(a->pointers,k);
-    } 
-    else {
-      g_hash_table_insert(a->pointers,oldk,p);
-    }
-  } 
-  else {
-    if(p == NULL) return;
-    g_hash_table_insert(a->pointers,lttv_key_copy(k),p);
-  }
-}
+  klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous))
+      lttv_attribute_named;
 
+  klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i, 
+      LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get;
 
-#ifdef EXT_ATTRIBS
-/* Sometimes the attributes must be accessed in bulk, sorted in different
-   ways. For this purpose they may be converted to arrays and sorted
-   multiple times. The keys used in the array belong to the lttv_attributes
-   object from which the array was obtained and are freed when it is
-   destroyed. Each element in the array is an lttv_attribute, a structure
-   containing the key, the value type, and a union containing a value of
-   that type. Multiple attributes with equal keys may be possible in some
-   implementations if their type differs. */
+  klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self,
+      LttvAttributeName name, LttvAttributeValue *v)) 
+      lttv_attribute_get_by_name;
 
+  klass->add = (LttvAttributeValue (*) (LttvIAttribute *self, 
+      LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add;
 
-typedef struct _lttv_attribute_fill_position  {
-  unsigned i;
-  lttv_attribute_type t;
-  lttv_attribute *a;
-} lttv_attribute_fill_position;
-
-
-static void lttv_attribute_fill(void *key, void *value, void *user_data) {
-  lttv_attribute_fill_position * p = (lttv_attribute_fill_position *)user_data;
-  lttv_attribute *a = p->a + p->i;
-
-  a->key = (lttv_key *)key;
-  a->t = p->t;
-  switch(p->t) {
-    case LTTV_INTEGER:
-      a->v.i = *((int *)value);
-    case LTTV_TIME:
-      a->v.t = *((lttv_time *)value);
-    case LTTV_DOUBLE:
-      a->v.d = *((double *)value);
-    case LTTV_POINTER:
-      a->v.p = value;
-  }
-  p->i++;
-}
+  klass->remove = (void (*) (LttvIAttribute *self, unsigned i)) 
+      lttv_attribute_remove;
 
+  klass->remove_by_name = (void (*) (LttvIAttribute *self,
+      LttvAttributeName name)) lttv_attribute_remove_by_name;
 
-lttv_attribute *lttv_attributes_array_get(lttv_attributes *a) {
-  unsigned size;
-  lttv_attribute *v;
-  lttv_attribute_fill_position p;
-
-  size = lttv_attributes_number(a);
-  v = g_new(lttv_attribute,size);
-
-  p.a = v;
-  p.i = 0;
-  p.t = LTTV_INTEGER;
-  g_hash_table_foreach(a->ints, lttv_attribute_fill, &p);
-  p.t = LTTV_TIME;
-  g_hash_table_foreach(a->times, lttv_attribute_fill, &p);
-  p.t = LTTV_DOUBLE;
-  g_hash_table_foreach(a->doubles, lttv_attribute_fill, &p);
-  p.t = LTTV_POINTER;
-  g_hash_table_foreach(a->pointers, lttv_attribute_fill, &p);
-  return v;
+  klass->create_subdir = (LttvIAttribute* (*) (LttvIAttribute *self, 
+      LttvAttributeName name)) lttv_attribute_create_subdir;
 }
 
 
-lttv_attribute *lttv_attribute_array_destroy(lttv_attribute *a) {
-  g_free(a);
-}
-
-
-void lttv_attribute_array_sort(lttv_attribute *a,
-    unsigned size, lttv_key_compare f,
-    void *compare_data)
+static guint
+quark_hash(gconstpointer key)
 {
-  
-  g_qsort_with_data(a, size, sizeof(lttv_attribute), f, 
-      compare_data);
+  return (guint)key;
 }
 
 
-int lttv_key_compare_priority(lttv_key *a, lttv_key *b, void *compare_data)
+static gboolean
+quark_equal(gconstpointer a, gconstpointer b)
 {
-  int i, res;
-  int *priority = (int *)compare_data;
-
-  g_assert(a->len == b->len);
-
-  for(i = 0 ; i < a->len ; i++) 
-  {
-    res = strcmp(lttv_string_id_to_string(lttv_key_index(a,priority[i])),
-        lttv_string_id_to_string(lttv_key_index(a,priority[i])));
-    if(res != 0) return res;
-  }
-  return 0;
+  return (a == b)
 }
 
-typedef struct _select_data {
-  lttv_attributes *a;
-  lttv_key *k;
-  void *user_data;
-  lttv_key_select select;
-} select_data;
-
-static void select_integer(void *key, void *value, void *user_data);
-static void select_double(void *key, void *value, void *user_data);
-static void select_time(void *key, void *value, void *user_data);
-static void select_pointer(void *key, void *value, void *user_data);
-
-lttv_attributes *lttv_attributes_select(lttv_attributes *a, lttv_key_select f, 
-    void *user_data)
+static void
+attribute_instance_init (GTypeInstance *instance, gpointer g_class)
 {
-  select_data *d;
-
-  d = g_new(select_data, 1);
-  d->a = lttv_attributes_new();
-  d->k = lttv_key_new();
-  d->user_data = user_data;
-  d->select = f;
-
-  g_hash_table_foreach(a->ints,select_integer, d);
-  g_hash_table_foreach(a->doubles,select_double, d);
-  g_hash_table_foreach(a->times,select_time, d);
-  g_hash_table_foreach(a->pointers,select_pointer, d);
+  LttvAttribute *self = (LttvAttribute *)instance;
+  self->names = g_hash_table_new(quark_hash, quark_equal);
+  self->attributes = g_array_new(FALSE, FALSE, 
+      sizeof(Attribute));
 }
 
-int lttv_key_select_spec(lttv_key *in, lttv_key *out, void *user_data)
-{
-  lttv_key_select_spec_data *d = (lttv_key_select_spec_data *)user_data;
-  int i;
-
-  /* not defined yet */
-  /* lttv_key_set_size(out, 0); */
-
-  for(i = 0 ; i < d->length ; i++) {
-    switch(d->spec[i]) {
-    case LTTV_KEEP:
-      break;
-
-    case LTTV_KEEP_EQUAL:
-      break;
-
-    case LTTV_KEEP_SMALLER:
-      break;
 
-    case LTTV_KEEP_GREATER:
-      break;
-
-    case LTTV_IGNORE:
-      break;
-
-    }
-  }
-
-  return 1;
-}
-
-static void select_integer(void *key, void *value, void *user_data)
-{
-  lttv_key *k = (lttv_key *)key;
-  int *pi = (int *)value;
-  select_data *d = (select_data *)user_data;
-
-  if(d->select(k,d->k,d->user_data)) {
-    *(lttv_attributes_get_integer(d->a,d->k)) += *pi;
-  }
-}
-
-static void select_double(void *key, void *value, void *user_data)
+static void
+attribute_finalize (LttvAttribute *self)
 {
-  lttv_key *k = (lttv_key *)key;
-  double *pf = (double *)value;
-  select_data *d = (select_data *)user_data;
-
-  if(d->select(k,d->k,d->user_data)) {
-    *(lttv_attributes_get_double(d->a,d->k)) += *pf;
-  }
+  g_hash_table_free(self->names);
+  g_array_free(self->attributes, TRUE);
+  G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_ATTRIBUTE_TYPE))->finalize(self);
 }
 
-static void select_time(void *key, void *value, void *user_data)
-{
-  lttv_key *k = (lttv_key *)key;
-  lttv_time *ptSum, *pt = (lttv_time *)value;
-  select_data *d = (select_data *)user_data;
-
-  if(d->select(k,d->k,d->user_data)) {
-    ptSum = lttv_attributes_get_time(d->a,d->k);
-    ptSum->tv_sec += pt->tv_sec;
-    ptSum->tv_nsec += pt->tv_nsec;
-  }
-}
 
-static void select_pointer(void *key, void *value, void *user_data)
+static void
+attribute_class_init (LttvAttributeClass *klass)
 {
-  lttv_key *k = (lttv_key *)key;
-  select_data *d = (select_data *)user_data;
+  GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
 
-  if(d->select(k,d->k,d->user_data)) {
-    lttv_attributes_set_pointer(d->a,d->k,value);
-  }
+  gobject_class->finalize = attribute_finalize;
 }
 
-
-
-
-
-#endif // EXT_ATTRIBS
This page took 0.027582 seconds and 4 git commands to generate.