Blame glib/deprecated/grel.c

Packit ae235b
/* GLIB - Library of useful routines for C programming
Packit ae235b
 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
Packit ae235b
 *
Packit ae235b
 * This library is free software; you can redistribute it and/or
Packit ae235b
 * modify it under the terms of the GNU Lesser General Public
Packit ae235b
 * License as published by the Free Software Foundation; either
Packit ae235b
 * version 2.1 of the License, or (at your option) any later version.
Packit ae235b
 *
Packit ae235b
 * This library is distributed in the hope that it will be useful,
Packit ae235b
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit ae235b
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit ae235b
 * Lesser General Public License for more details.
Packit ae235b
 *
Packit ae235b
 * You should have received a copy of the GNU Lesser General Public
Packit ae235b
 * License along with this library; if not, write to the Free
Packit ae235b
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Packit ae235b
 */
Packit ae235b
Packit ae235b
/*
Packit ae235b
 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
Packit ae235b
 * file for a list of people on the GLib Team.  See the ChangeLog
Packit ae235b
 * files for a list of changes.  These files are distributed with
Packit ae235b
 * GLib at ftp://ftp.gtk.org/pub/gtk/. 
Packit ae235b
 */
Packit ae235b
Packit ae235b
/* 
Packit ae235b
 * MT safe
Packit ae235b
 */
Packit ae235b
Packit ae235b
#include "config.h"
Packit ae235b
Packit ae235b
/* we know we are deprecated here, no need for warnings */
Packit ae235b
#define GLIB_DISABLE_DEPRECATION_WARNINGS
Packit ae235b
Packit ae235b
#include "grel.h"
Packit ae235b
Packit ae235b
#include <glib/gmessages.h>
Packit ae235b
#include <glib/gtestutils.h>
Packit ae235b
#include <glib/gstring.h>
Packit ae235b
#include <glib/gslice.h>
Packit ae235b
#include <glib/ghash.h>
Packit ae235b
Packit ae235b
#include <stdarg.h>
Packit ae235b
#include <string.h>
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * SECTION:relations
Packit ae235b
 * @title: Relations and Tuples
Packit ae235b
 * @short_description: tables of data which can be indexed on any
Packit ae235b
 *                     number of fields
Packit ae235b
 *
Packit ae235b
 * A #GRelation is a table of data which can be indexed on any number
Packit ae235b
 * of fields, rather like simple database tables. A #GRelation contains
Packit ae235b
 * a number of records, called tuples. Each record contains a number of
Packit ae235b
 * fields. Records are not ordered, so it is not possible to find the
Packit ae235b
 * record at a particular index.
Packit ae235b
 *
Packit ae235b
 * Note that #GRelation tables are currently limited to 2 fields.
Packit ae235b
 *
Packit ae235b
 * To create a GRelation, use g_relation_new().
Packit ae235b
 *
Packit ae235b
 * To specify which fields should be indexed, use g_relation_index().
Packit ae235b
 * Note that this must be called before any tuples are added to the
Packit ae235b
 * #GRelation.
Packit ae235b
 *
Packit ae235b
 * To add records to a #GRelation use g_relation_insert().
Packit ae235b
 *
Packit ae235b
 * To determine if a given record appears in a #GRelation, use
Packit ae235b
 * g_relation_exists(). Note that fields are compared directly, so
Packit ae235b
 * pointers must point to the exact same position (i.e. different
Packit ae235b
 * copies of the same string will not match.)
Packit ae235b
 *
Packit ae235b
 * To count the number of records which have a particular value in a
Packit ae235b
 * given field, use g_relation_count().
Packit ae235b
 *
Packit ae235b
 * To get all the records which have a particular value in a given
Packit ae235b
 * field, use g_relation_select(). To access fields of the resulting
Packit ae235b
 * records, use g_tuples_index(). To free the resulting records use
Packit ae235b
 * g_tuples_destroy().
Packit ae235b
 *
Packit ae235b
 * To delete all records which have a particular value in a given
Packit ae235b
 * field, use g_relation_delete().
Packit ae235b
 *
Packit ae235b
 * To destroy the #GRelation, use g_relation_destroy().
Packit ae235b
 *
Packit ae235b
 * To help debug #GRelation objects, use g_relation_print().
Packit ae235b
 *
Packit ae235b
 * GRelation has been marked as deprecated, since this API has never
Packit ae235b
 * been fully implemented, is not very actively maintained and rarely
Packit ae235b
 * used.
Packit ae235b
 **/
Packit ae235b
Packit ae235b
typedef struct _GRealTuples        GRealTuples;
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * GRelation:
Packit ae235b
 *
Packit ae235b
 * The #GRelation struct is an opaque data structure to represent a
Packit ae235b
 * [Relation][glib-Relations-and-Tuples]. It should
Packit ae235b
 * only be accessed via the following functions.
Packit ae235b
 **/
Packit ae235b
struct _GRelation
Packit ae235b
{
Packit ae235b
  gint fields;
Packit ae235b
  gint current_field;
Packit ae235b
  
Packit ae235b
  GHashTable   *all_tuples;
Packit ae235b
  GHashTable  **hashed_tuple_tables;
Packit ae235b
  
Packit ae235b
  gint count;
Packit ae235b
};
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * GTuples:
Packit ae235b
 * @len: the number of records that matched.
Packit ae235b
 *
Packit ae235b
 * The #GTuples struct is used to return records (or tuples) from the
Packit ae235b
 * #GRelation by g_relation_select(). It only contains one public
Packit ae235b
 * member - the number of records that matched. To access the matched
Packit ae235b
 * records, you must use g_tuples_index().
Packit ae235b
 **/
Packit ae235b
struct _GRealTuples
Packit ae235b
{
Packit ae235b
  gint      len;
Packit ae235b
  gint      width;
Packit ae235b
  gpointer *data;
Packit ae235b
};
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
tuple_equal_2 (gconstpointer v_a,
Packit ae235b
	       gconstpointer v_b)
Packit ae235b
{
Packit ae235b
  gpointer* a = (gpointer*) v_a;
Packit ae235b
  gpointer* b = (gpointer*) v_b;
Packit ae235b
  
Packit ae235b
  return a[0] == b[0] && a[1] == b[1];
Packit ae235b
}
Packit ae235b
Packit ae235b
static guint
Packit ae235b
tuple_hash_2 (gconstpointer v_a)
Packit ae235b
{
Packit ae235b
#if GLIB_SIZEOF_VOID_P > GLIB_SIZEOF_LONG
Packit ae235b
  /* In practise this snippet has been written for 64-bit Windows
Packit ae235b
   * where ints are 32 bits, pointers 64 bits. More exotic platforms
Packit ae235b
   * need more tweaks.
Packit ae235b
   */
Packit ae235b
  guint* a = (guint*) v_a;
Packit ae235b
Packit ae235b
  return (a[0] ^ a[1] ^ a[2] ^ a[3]);
Packit ae235b
#else
Packit ae235b
  gpointer* a = (gpointer*) v_a;
Packit ae235b
  
Packit ae235b
  return (gulong)a[0] ^ (gulong)a[1];
Packit ae235b
#endif
Packit ae235b
}
Packit ae235b
Packit ae235b
static GHashFunc
Packit ae235b
tuple_hash (gint fields)
Packit ae235b
{
Packit ae235b
  switch (fields)
Packit ae235b
    {
Packit ae235b
    case 2:
Packit ae235b
      return tuple_hash_2;
Packit ae235b
    default:
Packit ae235b
      g_error ("no tuple hash for %d", fields);
Packit ae235b
    }
Packit ae235b
  
Packit ae235b
  return NULL;
Packit ae235b
}
Packit ae235b
Packit ae235b
static GEqualFunc
Packit ae235b
tuple_equal (gint fields)
Packit ae235b
{
Packit ae235b
  switch (fields)
Packit ae235b
    {
Packit ae235b
    case 2:
Packit ae235b
      return tuple_equal_2;
Packit ae235b
    default:
Packit ae235b
      g_error ("no tuple equal for %d", fields);
Packit ae235b
    }
Packit ae235b
  
Packit ae235b
  return NULL;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_relation_new:
Packit ae235b
 * @fields: the number of fields.
Packit ae235b
 *
Packit ae235b
 * Creates a new #GRelation with the given number of fields. Note that
Packit ae235b
 * currently the number of fields must be 2.
Packit ae235b
 *
Packit ae235b
 * Returns: a new #GRelation.
Packit ae235b
 *
Packit ae235b
 * Deprecated: 2.26: Rarely used API
Packit ae235b
 **/
Packit ae235b
GRelation*
Packit ae235b
g_relation_new (gint fields)
Packit ae235b
{
Packit ae235b
  GRelation* rel = g_new0 (GRelation, 1);
Packit ae235b
  
Packit ae235b
  rel->fields = fields;
Packit ae235b
  rel->all_tuples = g_hash_table_new (tuple_hash (fields), tuple_equal (fields));
Packit ae235b
  rel->hashed_tuple_tables = g_new0 (GHashTable*, fields);
Packit ae235b
  
Packit ae235b
  return rel;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
relation_delete_value_tuple (gpointer tuple_key,
Packit ae235b
                             gpointer tuple_value,
Packit ae235b
                             gpointer user_data)
Packit ae235b
{
Packit ae235b
  GRelation *relation = user_data;
Packit ae235b
  gpointer *tuple = tuple_value;
Packit ae235b
  g_slice_free1 (relation->fields * sizeof (gpointer), tuple);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_relation_free_array (gpointer key, gpointer value, gpointer user_data)
Packit ae235b
{
Packit ae235b
  g_hash_table_destroy ((GHashTable*) value);
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_relation_destroy:
Packit ae235b
 * @relation: a #GRelation.
Packit ae235b
 *
Packit ae235b
 * Destroys the #GRelation, freeing all memory allocated. However, it
Packit ae235b
 * does not free memory allocated for the tuple data, so you should
Packit ae235b
 * free that first if appropriate.
Packit ae235b
 *
Packit ae235b
 * Deprecated: 2.26: Rarely used API
Packit ae235b
 **/
Packit ae235b
void
Packit ae235b
g_relation_destroy (GRelation *relation)
Packit ae235b
{
Packit ae235b
  gint i;
Packit ae235b
  
Packit ae235b
  if (relation)
Packit ae235b
    {
Packit ae235b
      for (i = 0; i < relation->fields; i += 1)
Packit ae235b
	{
Packit ae235b
	  if (relation->hashed_tuple_tables[i])
Packit ae235b
	    {
Packit ae235b
	      g_hash_table_foreach (relation->hashed_tuple_tables[i], g_relation_free_array, NULL);
Packit ae235b
	      g_hash_table_destroy (relation->hashed_tuple_tables[i]);
Packit ae235b
	    }
Packit ae235b
	}
Packit ae235b
Packit ae235b
      g_hash_table_foreach (relation->all_tuples, relation_delete_value_tuple, relation);
Packit ae235b
      g_hash_table_destroy (relation->all_tuples);
Packit ae235b
      
Packit ae235b
      g_free (relation->hashed_tuple_tables);
Packit ae235b
      g_free (relation);
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_relation_index:
Packit ae235b
 * @relation: a #GRelation.
Packit ae235b
 * @field: the field to index, counting from 0.
Packit ae235b
 * @hash_func: a function to produce a hash value from the field data.
Packit ae235b
 * @key_equal_func: a function to compare two values of the given field.
Packit ae235b
 *
Packit ae235b
 * Creates an index on the given field. Note that this must be called
Packit ae235b
 * before any records are added to the #GRelation.
Packit ae235b
 *
Packit ae235b
 * Deprecated: 2.26: Rarely used API
Packit ae235b
 **/
Packit ae235b
void
Packit ae235b
g_relation_index (GRelation   *relation,
Packit ae235b
		  gint         field,
Packit ae235b
		  GHashFunc    hash_func,
Packit ae235b
		  GEqualFunc   key_equal_func)
Packit ae235b
{
Packit ae235b
  g_return_if_fail (relation != NULL);
Packit ae235b
  
Packit ae235b
  g_return_if_fail (relation->count == 0 && relation->hashed_tuple_tables[field] == NULL);
Packit ae235b
  
Packit ae235b
  relation->hashed_tuple_tables[field] = g_hash_table_new (hash_func, key_equal_func);
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_relation_insert:
Packit ae235b
 * @relation: a #GRelation.
Packit ae235b
 * @...: the fields of the record to add. These must match the
Packit ae235b
 *       number of fields in the #GRelation, and of type #gpointer
Packit ae235b
 *       or #gconstpointer.
Packit ae235b
 *
Packit ae235b
 * Inserts a record into a #GRelation.
Packit ae235b
 *
Packit ae235b
 * Deprecated: 2.26: Rarely used API
Packit ae235b
 **/
Packit ae235b
void
Packit ae235b
g_relation_insert (GRelation   *relation,
Packit ae235b
		   ...)
Packit ae235b
{
Packit ae235b
  gpointer* tuple = g_slice_alloc (relation->fields * sizeof (gpointer));
Packit ae235b
  va_list args;
Packit ae235b
  gint i;
Packit ae235b
  
Packit ae235b
  va_start (args, relation);
Packit ae235b
  
Packit ae235b
  for (i = 0; i < relation->fields; i += 1)
Packit ae235b
    tuple[i] = va_arg (args, gpointer);
Packit ae235b
  
Packit ae235b
  va_end (args);
Packit ae235b
  
Packit ae235b
  g_hash_table_insert (relation->all_tuples, tuple, tuple);
Packit ae235b
  
Packit ae235b
  relation->count += 1;
Packit ae235b
  
Packit ae235b
  for (i = 0; i < relation->fields; i += 1)
Packit ae235b
    {
Packit ae235b
      GHashTable *table;
Packit ae235b
      gpointer    key;
Packit ae235b
      GHashTable *per_key_table;
Packit ae235b
      
Packit ae235b
      table = relation->hashed_tuple_tables[i];
Packit ae235b
      
Packit ae235b
      if (table == NULL)
Packit ae235b
	continue;
Packit ae235b
      
Packit ae235b
      key = tuple[i];
Packit ae235b
      per_key_table = g_hash_table_lookup (table, key);
Packit ae235b
      
Packit ae235b
      if (per_key_table == NULL)
Packit ae235b
	{
Packit ae235b
	  per_key_table = g_hash_table_new (tuple_hash (relation->fields), tuple_equal (relation->fields));
Packit ae235b
	  g_hash_table_insert (table, key, per_key_table);
Packit ae235b
	}
Packit ae235b
      
Packit ae235b
      g_hash_table_insert (per_key_table, tuple, tuple);
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_relation_delete_tuple (gpointer tuple_key,
Packit ae235b
			 gpointer tuple_value,
Packit ae235b
			 gpointer user_data)
Packit ae235b
{
Packit ae235b
  gpointer      *tuple = (gpointer*) tuple_value;
Packit ae235b
  GRelation     *relation = (GRelation *) user_data;
Packit ae235b
  gint           j;
Packit ae235b
  
Packit ae235b
  g_assert (tuple_key == tuple_value);
Packit ae235b
  
Packit ae235b
  for (j = 0; j < relation->fields; j += 1)
Packit ae235b
    {
Packit ae235b
      GHashTable *one_table = relation->hashed_tuple_tables[j];
Packit ae235b
      gpointer    one_key;
Packit ae235b
      GHashTable *per_key_table;
Packit ae235b
      
Packit ae235b
      if (one_table == NULL)
Packit ae235b
	continue;
Packit ae235b
      
Packit ae235b
      if (j == relation->current_field)
Packit ae235b
	/* can't delete from the table we're foreaching in */
Packit ae235b
	continue;
Packit ae235b
      
Packit ae235b
      one_key = tuple[j];
Packit ae235b
      
Packit ae235b
      per_key_table = g_hash_table_lookup (one_table, one_key);
Packit ae235b
      
Packit ae235b
      g_hash_table_remove (per_key_table, tuple);
Packit ae235b
    }
Packit ae235b
  
Packit ae235b
  if (g_hash_table_remove (relation->all_tuples, tuple))
Packit ae235b
    g_slice_free1 (relation->fields * sizeof (gpointer), tuple);
Packit ae235b
  
Packit ae235b
  relation->count -= 1;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_relation_delete:
Packit ae235b
 * @relation: a #GRelation.
Packit ae235b
 * @key: the value to compare with.
Packit ae235b
 * @field: the field of each record to match.
Packit ae235b
 *
Packit ae235b
 * Deletes any records from a #GRelation that have the given key value
Packit ae235b
 * in the given field.
Packit ae235b
 *
Packit ae235b
 * Returns: the number of records deleted.
Packit ae235b
 *
Packit ae235b
 * Deprecated: 2.26: Rarely used API
Packit ae235b
 **/
Packit ae235b
gint
Packit ae235b
g_relation_delete  (GRelation     *relation,
Packit ae235b
		    gconstpointer  key,
Packit ae235b
		    gint           field)
Packit ae235b
{
Packit ae235b
  GHashTable *table; 
Packit ae235b
  GHashTable *key_table;
Packit ae235b
  gint        count;
Packit ae235b
  
Packit ae235b
  g_return_val_if_fail (relation != NULL, 0);
Packit ae235b
Packit ae235b
  table = relation->hashed_tuple_tables[field];
Packit ae235b
  count = relation->count;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (table != NULL, 0);
Packit ae235b
  
Packit ae235b
  key_table = g_hash_table_lookup (table, key);
Packit ae235b
  
Packit ae235b
  if (!key_table)
Packit ae235b
    return 0;
Packit ae235b
  
Packit ae235b
  relation->current_field = field;
Packit ae235b
  
Packit ae235b
  g_hash_table_foreach (key_table, g_relation_delete_tuple, relation);
Packit ae235b
  
Packit ae235b
  g_hash_table_remove (table, key);
Packit ae235b
  
Packit ae235b
  g_hash_table_destroy (key_table);
Packit ae235b
  
Packit ae235b
  /* @@@ FIXME: Remove empty hash tables. */
Packit ae235b
  
Packit ae235b
  return count - relation->count;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_relation_select_tuple (gpointer tuple_key,
Packit ae235b
			 gpointer tuple_value,
Packit ae235b
			 gpointer user_data)
Packit ae235b
{
Packit ae235b
  gpointer    *tuple = (gpointer*) tuple_value;
Packit ae235b
  GRealTuples *tuples = (GRealTuples*) user_data;
Packit ae235b
  gint stride = sizeof (gpointer) * tuples->width;
Packit ae235b
  
Packit ae235b
  g_assert (tuple_key == tuple_value);
Packit ae235b
  
Packit ae235b
  memcpy (tuples->data + (tuples->len * tuples->width),
Packit ae235b
	  tuple,
Packit ae235b
	  stride);
Packit ae235b
  
Packit ae235b
  tuples->len += 1;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_relation_select:
Packit ae235b
 * @relation: a #GRelation.
Packit ae235b
 * @key: the value to compare with.
Packit ae235b
 * @field: the field of each record to match.
Packit ae235b
 *
Packit ae235b
 * Returns all of the tuples which have the given key in the given
Packit ae235b
 * field. Use g_tuples_index() to access the returned records. The
Packit ae235b
 * returned records should be freed with g_tuples_destroy().
Packit ae235b
 *
Packit ae235b
 * Returns: the records (tuples) that matched.
Packit ae235b
 *
Packit ae235b
 * Deprecated: 2.26: Rarely used API
Packit ae235b
 **/
Packit ae235b
GTuples*
Packit ae235b
g_relation_select (GRelation     *relation,
Packit ae235b
		   gconstpointer  key,
Packit ae235b
		   gint           field)
Packit ae235b
{
Packit ae235b
  GHashTable  *table;
Packit ae235b
  GHashTable  *key_table;
Packit ae235b
  GRealTuples *tuples; 
Packit ae235b
  gint count;
Packit ae235b
  
Packit ae235b
  g_return_val_if_fail (relation != NULL, NULL);
Packit ae235b
Packit ae235b
  table = relation->hashed_tuple_tables[field];
Packit ae235b
Packit ae235b
  g_return_val_if_fail (table != NULL, NULL);
Packit ae235b
  
Packit ae235b
  tuples = g_new0 (GRealTuples, 1);
Packit ae235b
  key_table = g_hash_table_lookup (table, key);
Packit ae235b
  
Packit ae235b
  if (!key_table)
Packit ae235b
    return (GTuples*)tuples;
Packit ae235b
  
Packit ae235b
  count = g_relation_count (relation, key, field);
Packit ae235b
  
Packit ae235b
  tuples->data = g_malloc (sizeof (gpointer) * relation->fields * count);
Packit ae235b
  tuples->width = relation->fields;
Packit ae235b
  
Packit ae235b
  g_hash_table_foreach (key_table, g_relation_select_tuple, tuples);
Packit ae235b
  
Packit ae235b
  g_assert (count == tuples->len);
Packit ae235b
  
Packit ae235b
  return (GTuples*)tuples;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_relation_count:
Packit ae235b
 * @relation: a #GRelation.
Packit ae235b
 * @key: the value to compare with.
Packit ae235b
 * @field: the field of each record to match.
Packit ae235b
 *
Packit ae235b
 * Returns the number of tuples in a #GRelation that have the given
Packit ae235b
 * value in the given field.
Packit ae235b
 *
Packit ae235b
 * Returns: the number of matches.
Packit ae235b
 *
Packit ae235b
 * Deprecated: 2.26: Rarely used API
Packit ae235b
 **/
Packit ae235b
gint
Packit ae235b
g_relation_count (GRelation     *relation,
Packit ae235b
		  gconstpointer  key,
Packit ae235b
		  gint           field)
Packit ae235b
{
Packit ae235b
  GHashTable  *table;
Packit ae235b
  GHashTable  *key_table;
Packit ae235b
  
Packit ae235b
  g_return_val_if_fail (relation != NULL, 0);
Packit ae235b
Packit ae235b
  table = relation->hashed_tuple_tables[field];
Packit ae235b
Packit ae235b
  g_return_val_if_fail (table != NULL, 0);
Packit ae235b
  
Packit ae235b
  key_table = g_hash_table_lookup (table, key);
Packit ae235b
  
Packit ae235b
  if (!key_table)
Packit ae235b
    return 0;
Packit ae235b
  
Packit ae235b
  return g_hash_table_size (key_table);
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_relation_exists:
Packit ae235b
 * @relation: a #GRelation.
Packit ae235b
 * @...: the fields of the record to compare. The number must match
Packit ae235b
 *       the number of fields in the #GRelation.
Packit ae235b
 *
Packit ae235b
 * Returns %TRUE if a record with the given values exists in a
Packit ae235b
 * #GRelation. Note that the values are compared directly, so that, for
Packit ae235b
 * example, two copies of the same string will not match.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if a record matches.
Packit ae235b
 *
Packit ae235b
 * Deprecated: 2.26: Rarely used API
Packit ae235b
 **/
Packit ae235b
gboolean
Packit ae235b
g_relation_exists (GRelation   *relation, ...)
Packit ae235b
{
Packit ae235b
  gpointer *tuple = g_slice_alloc (relation->fields * sizeof (gpointer));
Packit ae235b
  va_list args;
Packit ae235b
  gint i;
Packit ae235b
  gboolean result;
Packit ae235b
  
Packit ae235b
  va_start(args, relation);
Packit ae235b
  
Packit ae235b
  for (i = 0; i < relation->fields; i += 1)
Packit ae235b
    tuple[i] = va_arg(args, gpointer);
Packit ae235b
  
Packit ae235b
  va_end(args);
Packit ae235b
  
Packit ae235b
  result = g_hash_table_lookup (relation->all_tuples, tuple) != NULL;
Packit ae235b
  
Packit ae235b
  g_slice_free1 (relation->fields * sizeof (gpointer), tuple);
Packit ae235b
  
Packit ae235b
  return result;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_tuples_destroy:
Packit ae235b
 * @tuples: the tuple data to free.
Packit ae235b
 *
Packit ae235b
 * Frees the records which were returned by g_relation_select(). This
Packit ae235b
 * should always be called after g_relation_select() when you are
Packit ae235b
 * finished with the records. The records are not removed from the
Packit ae235b
 * #GRelation.
Packit ae235b
 *
Packit ae235b
 * Deprecated: 2.26: Rarely used API
Packit ae235b
 **/
Packit ae235b
void
Packit ae235b
g_tuples_destroy (GTuples *tuples0)
Packit ae235b
{
Packit ae235b
  GRealTuples *tuples = (GRealTuples*) tuples0;
Packit ae235b
  
Packit ae235b
  if (tuples)
Packit ae235b
    {
Packit ae235b
      g_free (tuples->data);
Packit ae235b
      g_free (tuples);
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_tuples_index:
Packit ae235b
 * @tuples: the tuple data, returned by g_relation_select().
Packit ae235b
 * @index_: the index of the record.
Packit ae235b
 * @field: the field to return.
Packit ae235b
 *
Packit ae235b
 * Gets a field from the records returned by g_relation_select(). It
Packit ae235b
 * returns the given field of the record at the given index. The
Packit ae235b
 * returned value should not be changed.
Packit ae235b
 *
Packit ae235b
 * Returns: the field of the record.
Packit ae235b
 *
Packit ae235b
 * Deprecated: 2.26: Rarely used API
Packit ae235b
 **/
Packit ae235b
gpointer
Packit ae235b
g_tuples_index (GTuples     *tuples0,
Packit ae235b
		gint         index,
Packit ae235b
		gint         field)
Packit ae235b
{
Packit ae235b
  GRealTuples *tuples = (GRealTuples*) tuples0;
Packit ae235b
  
Packit ae235b
  g_return_val_if_fail (tuples0 != NULL, NULL);
Packit ae235b
  g_return_val_if_fail (field < tuples->width, NULL);
Packit ae235b
  
Packit ae235b
  return tuples->data[index * tuples->width + field];
Packit ae235b
}
Packit ae235b
Packit ae235b
/* Print
Packit ae235b
 */
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_relation_print_one (gpointer tuple_key,
Packit ae235b
		      gpointer tuple_value,
Packit ae235b
		      gpointer user_data)
Packit ae235b
{
Packit ae235b
  gint i;
Packit ae235b
  GString *gstring;
Packit ae235b
  GRelation* rel = (GRelation*) user_data;
Packit ae235b
  gpointer* tuples = (gpointer*) tuple_value;
Packit ae235b
Packit ae235b
  gstring = g_string_new ("[");
Packit ae235b
  
Packit ae235b
  for (i = 0; i < rel->fields; i += 1)
Packit ae235b
    {
Packit ae235b
      g_string_append_printf (gstring, "%p", tuples[i]);
Packit ae235b
      
Packit ae235b
      if (i < (rel->fields - 1))
Packit ae235b
	g_string_append (gstring, ",");
Packit ae235b
    }
Packit ae235b
  
Packit ae235b
  g_string_append (gstring, "]");
Packit ae235b
  g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "%s", gstring->str);
Packit ae235b
  g_string_free (gstring, TRUE);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_relation_print_index (gpointer tuple_key,
Packit ae235b
			gpointer tuple_value,
Packit ae235b
			gpointer user_data)
Packit ae235b
{
Packit ae235b
  GRelation* rel = (GRelation*) user_data;
Packit ae235b
  GHashTable* table = (GHashTable*) tuple_value;
Packit ae235b
  
Packit ae235b
  g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "*** key %p", tuple_key);
Packit ae235b
  
Packit ae235b
  g_hash_table_foreach (table,
Packit ae235b
			g_relation_print_one,
Packit ae235b
			rel);
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_relation_print:
Packit ae235b
 * @relation: a #GRelation.
Packit ae235b
 *
Packit ae235b
 * Outputs information about all records in a #GRelation, as well as
Packit ae235b
 * the indexes. It is for debugging.
Packit ae235b
 *
Packit ae235b
 * Deprecated: 2.26: Rarely used API
Packit ae235b
 **/
Packit ae235b
void
Packit ae235b
g_relation_print (GRelation *relation)
Packit ae235b
{
Packit ae235b
  gint i;
Packit ae235b
  
Packit ae235b
  g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "*** all tuples (%d)", relation->count);
Packit ae235b
  
Packit ae235b
  g_hash_table_foreach (relation->all_tuples,
Packit ae235b
			g_relation_print_one,
Packit ae235b
			relation);
Packit ae235b
  
Packit ae235b
  for (i = 0; i < relation->fields; i += 1)
Packit ae235b
    {
Packit ae235b
      if (relation->hashed_tuple_tables[i] == NULL)
Packit ae235b
	continue;
Packit ae235b
      
Packit ae235b
      g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "*** index %d", i);
Packit ae235b
      
Packit ae235b
      g_hash_table_foreach (relation->hashed_tuple_tables[i],
Packit ae235b
			    g_relation_print_index,
Packit ae235b
			    relation);
Packit ae235b
    }
Packit ae235b
  
Packit ae235b
}