/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * $Id: gxsnmp_database_table.c,v 1.2 2000/09/22 16:02:37 gregm Exp $
 *
 * Copyright 2000 Larry Liimatainen
 * gxsnmp_database_table.c -- database table interface.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc.,  59 Temple Place - Suite 330, Cambridge, MA 02139, USA.
 *
 *  gxsnmp_database_table.c
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gnome.h>

#include "gxsnmp_database_table.h"

/****************************************************************************
 * Private methods to this module
 **/
/** Caculate the size of all the fields in a table. **/
gint
gxsnmp_db_field_size (GList *gl)
{
    gxsnmp_db_field   *field;
    gint              i;

    i = 0;
    while (gl)
        {
            field = (gxsnmp_db_field *)gl->data;
            switch (field->type)
                {
                case TD_GUINT:
                case TD_GINT:
                case TD_PGUINT:
                case TD_PGINT:
                    i += sizeof (gint);
                    break;
                case TD_GSTR:
                case TD_PGSTR:
                case TD_PGL:
                    i += sizeof (gpointer);
                    break;
                case TD_GDOUBLE:
                case TD_PGDOUBLE:
                    i += sizeof (gdouble);
                    break;
                default:
                    g_warning ("Unknown field type for %s,\n", field->name);
                    break;
                }
            gl = g_list_next (gl);
        }
    return i;
}
/** Set the field offets **/
gint
gxsnmp_db_fields_offset (GList *gl)
{
    gxsnmp_db_field    *field;
    gint               offset;

    offset = 0;
    while (gl)
        {
            field         = (gxsnmp_db_field *)gl->data;
            field->offset = offset;
            switch (field->type)
                {
                case TD_GUINT:
                case TD_GINT:
                case TD_PGUINT:
                case TD_PGINT:
                    offset += sizeof (gint);
                    break;
                case TD_GSTR:
                case TD_PGSTR:
                case TD_PGL:
                    offset += sizeof (gpointer);
                    break;
                case TD_GDOUBLE:
                case TD_PGDOUBLE:
                    offset += sizeof (gdouble);
                    break;
                default:
                    g_warning ("Unknown field type for %s.\n", field->name);
                    break;
                }
            gl = g_list_next (gl);
        }
    return 0;
}
/****************************************************************************
 * Private data to this module.
 **/

GList *table_desc = NULL;               /* List of table descriptors */



/****************************************************************************
 * Public functions.
 **/
/**
 * gxsnmp_db_table_size:
 * -- This and the offset code should probably be collapsed into a one
 * pass thing.
 **/
gint
gxsnmp_db_table_size ()
{
    gxsnmp_db_table    *table;
    GList              *gl;
    gint               i;

    gl = table_desc;
    while (gl)
        {
            table = (gxsnmp_db_table *)gl->data;
            i     = sizeof(gpointer) * 5;
            i    += gxsnmp_db_field_size ((GList *)table->fields);
            table->size = i;
            gl = g_list_next (gl);
        }
    return 0;
}
/**
 * gxsnmp_db_table_offset:
 *
 * -- Collapse this function and the previous one into a signal pass.
 **/
gint
gxsnmp_db_table_offset ()
{
    gxsnmp_db_table  *table;
    GList            *gl;

    gl = table_desc;
    while (gl)
        {
            table = (gxsnmp_db_table *)gl->data;
            gxsnmp_db_fields_offset ((GList *)table->fields);
            gl = g_list_next (gl);
        }
    return 0;
}
/**
 * gxsnmp_db_field_new:
 *
 * Allocate a new gxsnmp_db_field structure and return a pointer to
 * the freshly allocated structure.
 *
 * Return value: The freshly allocated pointer, NULL is returned on
 * failure.
 **/

gxsnmp_db_field *
gxsnmp_db_field_new()
{
    gxsnmp_db_field  *retval;
    /* TODO: Add ref counting. */
    retval = g_malloc0 (sizeof (gxsnmp_db_field *));
    return (retval != NULL) ? retval : NULL;
}

/**
 * gxsnmp_db_field_offset:
 * @table: The gxsnmp_db_table_descriptor for the table in question.
 * @name:  The field entry's name we are after.
 *
 * Will lookup and return the offset into a table for the given field
 * passed in through the field argument.
 *
 * Return value: Offset to the member in the structure, -1 otherwise.
 **/
gint
gxsnmp_db_field_offset (gxsnmp_db_table *table, const gchar *name)
{
  GList           *gl;
  gxsnmp_db_field *field;

  gl = table->fields;
  while (gl)
    {
      field = gl->data;
      if (!g_strncasecmp (name, field->name, strlen (field->name)))
	return field->offset;
      gl = g_list_next (gl);
    }
  return -1;
}
/**
 * gxsnmp_db_field_type:
 * @table: The gxsnmp_db_table_descriptor for the table in question.
 * @name:  The field entry's name we are after.
 *
 * This function will lookup and return the type of the field for a
 * given field in a given table.
 *
 * Return value: field type or -1 on error.
 **/
gint
gxsnmp_db_field_type (gxsnmp_db_table *table, const gchar *name)
{
  GList            *gl;
  gxsnmp_db_field  *field;
  gl = table->fields;
  while (gl)
    {
      field = gl->data;
      if (!g_strncasecmp (name, field->name, strlen (field->name)))
	return field->type;
      gl = g_list_next (gl);
    }
  return -1;
}
/**
 * gxsnmp_db_table_new:
 *
 * Allocate and initialize the storage for a new table.
 *
 * Return value: A newly allocated gxsnmp_db_table structure, NULL on failure.
 **/
gxsnmp_db_table *
gxsnmp_db_table_new ()
{
    gxsnmp_db_table   *retval;

    /* TODO: add ref counting here. */
    retval = g_malloc0 (sizeof (gxsnmp_db_table *));

    retval->fields = NULL;
    
    return (retval != NULL) ? retval : NULL;
}
/**
 * gxsnmp_db_table_find:
 * @name: The name of the table we are searching for.
 *
 * This function will find a table by its name.
 *
 * Return value: The gxsnmp_db_table_descriptor of the table in question,
 * NULL if not found.
 **/
gxsnmp_db_table *
gxsnmp_db_table_find (const gchar *name)
{
  GList   *gl;
  gxsnmp_db_table *table;

  gl = table_desc;
  while (gl)
    {
      table = gl->data;
      if (!g_strncasecmp (name, table->name, strlen (table->name)))
	return table;
      gl = g_list_next (gl);
    }
  return NULL;
}
/* EOF */
