Logo Search packages:      
Sourcecode: gaby version File versions  Download package

database.c

/*  Database library (Double Linked List)
   15-7-1998

   Copyright (C) 1998  Ron Bessems
   Contact me via email at R.E.M.W.Bessems@stud.tue.nl

   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., 675 Mass Ave, Cambridge, MA 02139, USA.


   Todo: 
   File locking.

   Changes: 

   1-11-1998
   Fixed ? the delete current function  (ron) 
   2-11-1998
   Added Qsort.
   6-11-1998
   Added filter, not quite done, check move_previous move_last
   3-1-1999
   Added the primary key functions,
   removed the recnum shit.
   added change data.         
   9-1-1999
   removed c++ style comments.
   Gnu compiler doesn't care but the NSG-Indy does.
   16-1-1999
   changed the sort function internally.
   now the database is sorted on the keys while adding
   a field (this might change) 
 */


#define DATABASE

#include <format_plugin.h>
#include "database.h"
#include "config_vid.h"

static int (*c) (const void *, const void *);

int 
change_data (struct list *lijst, void *data, int size, int key)
{
  struct field *f;

  database_error = 0;
  if (lijst == NULL)
    {
      database_error = 4;
      return -1;
    }
  f = lijst->lookup[key];
  if (f == NULL)
    {
      database_error = 3;
      return -1;
    }
  g_free (f->data);
  if (size > 10000)
    {
      database_error = 2;
      return -1;
    }

  f->data = g_malloc (size);
  if (f->data == NULL)
    {
      database_error = 2;
      return -1;
    }
  memcpy (f->data, data, size);
  f->size = size;
  return 0;
}

unsigned int 
get_key (struct list *lijst)
{
  database_error = 0;
  if (lijst == NULL)
    {
      database_error = 4;
      return 0;
    }
  return lijst->huidige->key;
}


static int 
sort_list_basic (struct list *lijst, int (*comp) (const void *, const void *))
{
  struct field *array[MAXREC];
  int i;
  int (*filter) (const void *);
  i = 0;

  database_error = 0;

  if (lijst == NULL)
    {
      database_error = 4;
      return -1;
    }
  if (lijst->totaal == 0 || comp == NULL)
    {
      database_error = 5;
      return -2;
    }

  /* First kill and store the filter */
  filter = lijst->filter;
  lijst->filter = NULL;

  move_first (lijst);
  do
    {
      array[i] = lijst->huidige;
      i++;
    }
  while (move_next (lijst) == 0);
  qsort (array, lijst->totaal, sizeof (struct field *), comp);
  lijst->eerste = array[0];
  array[0]->vorige = NULL;
  array[0]->volgende = array[1];

  lijst->laatste = array[lijst->totaal - 1];
  array[lijst->totaal - 1]->volgende = NULL;
  array[lijst->totaal - 1]->vorige = array[lijst->totaal - 2];

  for (i = 1; i < lijst->totaal - 1; i++)
    {
      array[i]->vorige = array[i - 1];
      array[i]->volgende = array[i + 1];
    }

  /* restore the filter; */
  lijst->filter = filter;

  return 0;
}

static int 
sort_on_key (const void *data1, const void *data2)
{
  const struct field *f1;
  const struct field *f2;
  f1 = (struct field *) * (int *) data1;
  f2 = (struct field *) * (int *) data2;
  return (f1->key > f2->key ? 1 : -1);
}

static int 
sort_on_user (const void *d, const void *e)
{
  const struct field *d1;
  const struct field *d2;
  d1 = (struct field *) * (int *) d;
  d2 = (struct field *) * (int *) e;
  return c (d1->data, d2->data);
}


int 
sort_list (struct list *lijst, int (*comp) (const void *, const void *))
{
  c = comp;
  return sort_list_basic (lijst, sort_on_user);
}

int 
sort_key_list (struct list *lijst)
{
  return sort_list_basic (lijst, sort_on_key);
}

static struct list *
add_to_list_basic (struct list *lijst, void *data, int size, int key)
{
  struct field *volgende;
  struct field *vorige;
  struct field *lus;
  /* LOOKUP */
  int temp;

  database_error = 0;

  if (key > MAXREC)
    {
      database_error = 1;
      return lijst;
    }

  if (lijst == NULL)
    {
      lijst = (struct list *) g_malloc (sizeof (struct list));
      lijst->filter = NULL;
      lijst->eerste = NULL;
      lijst->huidige = NULL;
      lijst->totaal = 0;
      /* LOOKUP */
      for (temp = 0; temp < MAXREC; temp++)
      {
        lijst->lookup[temp] = NULL;
      }
    }
  lus = lijst->eerste;
  vorige = NULL;
  volgende = NULL;
  /* Search last item, store this in the vorige pointer */
  while (lus != NULL)
    {
      vorige = lus;
      lus = lus->volgende;
    }
  /* Allocate memory space for chain struct */
  volgende = (struct field *) g_malloc (sizeof (struct field));

  if (volgende == NULL)
    {                   /* This should never happen ! */
      database_error = 2;
      return NULL;
    }
  /* Start  new pointer chain */
  if (vorige == NULL)
    {
      volgende->vorige = NULL;
      lijst->eerste = volgende;
    }
  else
    {
      volgende->vorige = vorige;
      vorige->volgende = volgende;
    }
  vorige = volgende;
  volgende->volgende = NULL;

  /* make a deep copy of the data */
  /* Hack if the size of the array > 10kb exit */
  if (size > 10000)
    {
      database_error = 2;
      return NULL;
    }

  volgende->data = g_malloc (size);
  if (volgende->data == NULL)
    {
      database_error = 2;
      return NULL;
    }
  memcpy (volgende->data, data, size);
  volgende->size = size;
  volgende->key = key;
  /* LOOKUP */
  lijst->lookup[key] = volgende;

  lijst->huidige = volgende;
  lijst->laatste = volgende;
  lijst->totaal = lijst->totaal + 1;
  return lijst;
}

/* return value 0 means error */
static unsigned int 
get_free_key (struct list *lijst)
{
  unsigned int teller;
#ifndef EASY_KEY
  int laatste;
  laatste=MAXREC+1;
#endif
  database_error = 0;
  if (lijst == NULL)
    return 1;
#ifndef EASY_KEY

  /* first look for last key */
  for (teller = 1; teller < MAXREC; teller++)
    {
      if (lijst->lookup[teller] != NULL)
      {
        laatste = teller;
      }
    }
  /* take the next */
  laatste++;
  /* check if this is in the database range */
  if (laatste < MAXREC)
    return laatste;           /* yes */

#endif      /* EASY_KEY */
  /* if not start at the bottom again  EASY_KEY */
  for (teller = 1; teller < MAXREC; teller++)
    {
      if (lijst->lookup[teller] == NULL)
      return teller;
    }
  database_error = 1;
  return 0;             /* all key are taken, sorry... */
}




int 
set_filter (struct list *lijst, int (*filter) (const void *))
{
  database_error = 0;
  if (lijst == NULL)
    {
      database_error = 4;
      return -1;
    }
  lijst->filter = filter;

  return 0;

}


int 
save_list (struct list *lijst, char *naam)
{
#ifndef READONLY
  int fd;
  struct field *i;
  database_error = 0;

  if (lijst == NULL)
    {
      database_error = 4;
      return -1;        /* Geen lijst */
    }
  /* if (lijst->eerste==NULL)
     {
     database_error=6;
     return -2;   
     } */
#ifndef DJGPP
  fd = open (naam, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR |
           S_IWUSR | S_IRGRP | S_IROTH);
#else
  fd = open (naam, O_BINARY | O_RDWR | O_CREAT | O_TRUNC, S_IRUSR |
           S_IWUSR | S_IRGRP | S_IROTH);
#endif
  if (fd < 0)
    {
      printf ("Error saving file.\nPlease check permissions.\n");
      return -5;
    }
  i = lijst->eerste;
  while (i != NULL)
    {
      write (fd, &i->size, sizeof (i->size));
      write (fd, &i->key, sizeof (i->key));
      write (fd, i->data, i->size);
      i = i->volgende;
    }
  close (fd);
#else
  printf ("*** Write support is not built in. ***\n");
#endif
  return 0;
}


struct list *
load_list (struct list *lijst, char *naam)
{
  int fd;
  unsigned int key;
  int size;
  char *buffer;
  buffer = NULL;
#ifndef DJGPP
  fd = open (naam, O_RDONLY);
#else
  fd = open (naam, O_RDONLY | O_BINARY);
#endif
  if (fd < 0)
    {
#ifndef CONVERT
      printf ("Read error, check input file %s.\n", naam);
#endif
      return lijst;
    }
  while (read (fd, &size, sizeof (size)) > 0)
    {
      read (fd, &key, sizeof (unsigned int));
      buffer = realloc (buffer, size);
      read (fd, buffer, size);
      lijst = add_to_list_basic (lijst, buffer, size, key);
    }
  return lijst;
}



int 
delete_current (struct list *lijst)
{
  struct field *volg;
  struct field *vorig;
  struct field *huidig;

  if (lijst == NULL)
    return -1;                /* Geen lijst */
  if (lijst->eerste == NULL)
    return -2;                /* Niks in lijst */
  if (lijst->huidige == NULL)
    return -3;                /* Geen huidige ahhhh */

  huidig = lijst->huidige;
  volg = huidig->volgende;
  lijst->lookup[huidig->key] = NULL;
  vorig = huidig->vorige;

  if (vorig != NULL)
    vorig->volgende = volg;
  if (volg != NULL)
    volg->vorige = vorig;
  if (huidig->data != NULL)
    g_free (huidig->data);
  g_free (huidig);
  if (vorig != NULL)
    {
      lijst->huidige = vorig;
    }
  if (vorig == NULL && volg != NULL)
    {
      lijst->huidige = volg;
      lijst->eerste = volg;
    }
  if (volg == NULL && vorig != NULL)
    {
      lijst->huidige = vorig;
      lijst->laatste = vorig;
    }

  if (vorig == NULL && volg == NULL)
    {
      lijst->huidige = NULL;
      lijst->totaal = 1;
      lijst->laatste = NULL;
      lijst->eerste = NULL;
    }

  lijst->totaal = lijst->totaal - 1;
  return 0;
}



int 
move_next (struct list *lijst)
{
  struct field *volg;

  if (lijst == NULL)
    return -1;                /* Geen lijst */
  if (lijst->eerste == NULL)
    return -2;                /* Niks in lijst */
  if (lijst->huidige == NULL)
    return -3;                /* Geen huidige ahhhh */

  volg = lijst->huidige;
  if (volg->volgende == NULL)
    return -4;                /* geen volgende */
  if (lijst->filter == NULL)
    {
      lijst->huidige = volg->volgende;

    }
  else
    {
      do
      {
        volg = lijst->huidige;
        if (volg->volgende == NULL)
          return -4;          /* geen volgende */
        lijst->huidige = volg->volgende;
      }
      while (lijst->filter (lijst->huidige->data) == 0);
    }



  return 0;
}

int 
move_first (struct list *lijst)
{
  struct field *volg;

  if (lijst == NULL)
    return -1;                /* Geen lijst */
  if (lijst->eerste == NULL)
    return -2;                /* Niks in lijst */
  if (lijst->huidige == NULL)
    return -3;                /* Geen huidige ahhhh */


  if (lijst->filter == NULL)
    {
      lijst->huidige = lijst->eerste;
    }
  else
    {
      volg = lijst->eerste;
      lijst->huidige = volg;
      while (lijst->filter (lijst->huidige->data) == 0)
      {
        if (volg->volgende == NULL)
          return -2;
        lijst->huidige = volg->volgende;
        volg = lijst->huidige;

      }
    }




  return 0;
}

int 
move_last (struct list *lijst)
{
  struct field *volg;
  if (lijst == NULL)
    return -1;                /* Geen lijst */
  if (lijst->eerste == NULL)
    return -2;                /* Niks in lijst */
  if (lijst->huidige == NULL)
    return -3;                /* Geen huidige ahhhh */
  lijst->huidige = lijst->laatste;

  if (lijst->filter == NULL)
    {
      lijst->huidige = lijst->laatste;
    }
  else
    {
      lijst->huidige = lijst->laatste;
      volg = lijst->huidige;
      while (lijst->filter (lijst->huidige->data) == 0)
      {
        if (volg->vorige == NULL)
          return -2;
        lijst->huidige = volg->vorige;
        volg = lijst->huidige;
      }
    }

  return 0;
}

int 
move_previous (struct list *lijst)
{
  struct field *volg;

  if (lijst == NULL)
    return -1;                /* Geen lijst */
  if (lijst->eerste == NULL)
    return -2;                /* Niks in lijst */
  if (lijst->huidige == NULL)
    return -3;                /* Geen huidige ahhhh */

  volg = lijst->huidige;
  if (volg->vorige == NULL)
    return -4;                /* geen vorige */



  volg = lijst->huidige;
  if (volg->vorige == NULL)
    return -4;                /* geen volgende */
  if (lijst->filter == NULL)
    {
      lijst->huidige = volg->vorige;
    }
  else
    {
      do
      {
        volg = lijst->huidige;
        if (volg->vorige == NULL)
          return -4;          /* geen volgende */
        lijst->huidige = volg->vorige;
      }
      while (lijst->filter (lijst->huidige->data) == 0);
    }



  return 0;
}

void *
get_data (struct list *lijst)
{
  if (lijst == NULL)
    return (void *) -1;       /* Geen lijst */
  if (lijst->eerste == NULL)
    return (void *) -2;       /* Niks in lijst */
  if (lijst->huidige == NULL)
    return (void *) -3;       /* Geen huidige ahhhh */
  return lijst->huidige->data;
}


int 
free_list (struct list *lijst)
{
  struct field *volgende;
  struct field *huidig;
  if (lijst == NULL)
    return -1;                /* Geen lijst */
  if (lijst->eerste == NULL)
    return -2;                /* Niks in lijst */
  volgende = lijst->eerste;

  while (volgende != NULL)
    {
      huidig = volgende;
      volgende = volgende->volgende;

      if (huidig->data != NULL)
      g_free (huidig->data);
      g_free (huidig);
    }
  g_free (lijst);
  return 0;
}


struct list *
add_to_list (struct list *lijst, void *data, int size)
{
  int key;
  struct list *ret;
  key = get_free_key (lijst);
  ret = add_to_list_basic (lijst, data, size, key);
  sort_key_list (ret);
  return ret;
}

int 
goto_key (struct list *lijst, int key)
{
  struct field *huid;

  if (lijst == NULL)
    return -1;                /* Geen lijst */
  if (lijst->eerste == NULL)
    return -2;                /* Niks in lijst */
  if (lijst->huidige == NULL)
    return -3;                /* Geen huidige ahhhh */
  if (key > MAXREC)
    return -6;

  huid = lijst->lookup[key];
  if (huid == NULL)
    return -3;
  lijst->huidige = huid;
  return 0;
}

int 
goto_field (struct list *lijst, int veld)
{
  return goto_key (lijst, veld);
}


int 
get_total_field (struct list *lijst)
{
  if (lijst == NULL)
    return 0;
  else
    return lijst->totaal;
}

Generated by  Doxygen 1.6.0   Back to index