/* ---------------------------------------------------------------------
   (c) ED 2003
   Project      : PROJECT
   Function     : generic objet manager
   Module       : OBJ
   File         : obj.c
   Created      : 22-11-2003
   Modified     : 26-11-2003
   --------------------------------------------------------------------- */

/* ---------------------------------------------------------------------
   Log

   0.0 22-11-2003 Created
   1.0 24-11-2003 Initial version
   1.1 26-11-2003 Full abstration (try)

   --------------------------------------------------------------------- */
#ifdef __cplusplus
#error This is not C++. Please use a C compiler.
#endif

#include "ed/inc/obj.h"
#include "ed/inc/sysalloc.h"
#include "ed/inc/sys.h"

/* private macro definitions =========================================== */

#define VER "1.1"

#define ID "OBJ"
#define CPY "(c) ED 2003"

/* private constants =================================================== */

/* private types ======================================================= */

/* private structures ================================================== */

struct obj
{
   size_t size;
   size_t number;
   void *pdata;

   obj_out_f *pf;
   void *p_usr;
};

/* private functions =================================================== */

/* ---------------------------------------------------------------------
   get_addr ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
#if OBJ_ABSTRACTION
static void *get_addr (OBJ_RO this, size_t ndx)
#else
static void *get_addr (obj_s const *this, size_t ndx)
#endif
{
   char *p = NULL;

   if (ndx < this->number)
   {
      if (this->pdata != NULL)
      {
         p = this->pdata;
         p += ndx * (this->size);
      }
   }

   return p;
}

/* public internal functions =========================================== */

/* entry points ======================================================== */

/* ---------------------------------------------------------------------
   obj_sid ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
char const *obj_sid (void)
{
   return ID " " CPY;
}

/* ---------------------------------------------------------------------
   obj_sver ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
char const *obj_sver (void)
{
   return VER;
}

/* ---------------------------------------------------------------------
   obj_create ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
#if OBJ_ABSTRACTION
OBJ_RW obj_create (size_t size, size_t number)
#else
obj_s *obj_create (size_t size, size_t number)
#endif
{
   struct obj *this = NULL;

   if (size <= ((size_t) - 1) / number)
   {
      this = malloc (sizeof *this);

      if (this != NULL)
      {
         CLR (this, struct obj);

         this->pdata = malloc (size * number);

         if (this->pdata != NULL)
         {
            this->size = size;
            this->number = number;

            /* Nota : on ne peut initialiser la zone de donnees,
             * car on ne connait pas le type.
             */
         }
      }
      else
      {
         obj_delete (this);
         this = NULL;
      }
   }
   return this;
}

/* ---------------------------------------------------------------------
   obj_delete ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
#if OBJ_ABSTRACTION
void obj_delete (OBJ_RW this)
#else
void obj_delete (obj_s * this)
#endif
{
   if (this != NULL)
   {
      free (this->pdata);
      free (this);
   }
}

/* ---------------------------------------------------------------------
   obj_init ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
#if OBJ_ABSTRACTION
obj_err_e obj_init (OBJ_RW this)
#else
obj_err_e obj_init (obj_s * this)
#endif
{
   obj_err_e err = OBJ_OK;

   if (this != NULL)
   {

/*   -> Insert your code here */

   }
   else
   {
      err = OBJ_ERR_CONTEXT;
   }
   return err;
}

/* ---------------------------------------------------------------------
   obj_install_out ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
#if OBJ_ABSTRACTION
obj_err_e obj_install_out (OBJ_RW this, obj_out_f * pf, void *p_usr)
#else
obj_err_e obj_install_out (obj_s * this, obj_out_f * pf, void *p_usr)
#endif
{
   obj_err_e err = OBJ_OK;

   if (this != NULL)
   {
      this->pf = pf;
      this->p_usr = p_usr;
   }
   else
   {
      err = OBJ_ERR_CONTEXT;
   }
   return err;
}

/* ---------------------------------------------------------------------
   obj_in ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
#if OBJ_ABSTRACTION
obj_err_e obj_in (OBJ_RW this, int data)
#else
obj_err_e obj_in (obj_s * this, int data)
#endif
{
   obj_err_e err = OBJ_OK;

   if (this != NULL)
   {
      if (this->pf != NULL)
      {
         int ret = (*this->pf) (this->p_usr, data);
         if (ret != 0)

         {
            err = OBJ_ERR_CB_OUT;
         }
      }
   }
   else
   {
      err = OBJ_ERR_CONTEXT;
   }
   return err;
}

/* ---------------------------------------------------------------------
   obj_write ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
#if OBJ_ABSTRACTION
obj_err_e obj_write (OBJ_RW const this
                     ,void const *const pdata
                     ,size_t const ndx)
#else
obj_err_e obj_write (obj_s * const this
                     ,void const *const pdata
                     ,size_t const ndx)
#endif
{
   obj_err_e err = OBJ_OK;

   if (this != NULL)
   {
      if (pdata != NULL)
      {
         void *const p = get_addr (this, ndx);

         if (p != NULL)
         {
            memcpy (p, pdata, this->size);
         }
         else
         {
            err = OBJ_ERR_PARAMETER;
         }
      }
      else
      {
         err = OBJ_ERR_PARAMETER;
      }
   }
   else
   {
      err = OBJ_ERR_CONTEXT;
   }
   return err;
}

/* ---------------------------------------------------------------------
   obj_write ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
#if OBJ_ABSTRACTION
obj_err_e obj_read (OBJ_RO const this
                    ,void *const pdata
                    ,size_t const ndx)
#else
obj_err_e obj_read (obj_s const *const this
                    ,void *const pdata
                    ,size_t const ndx)
#endif
{
   obj_err_e err = OBJ_OK;

   if (this != NULL)
   {
      if (pdata != NULL)
      {
         void *const p = get_addr (this, ndx);

         if (p != NULL)
         {
            memcpy (pdata, p, this->size);
         }
         else
         {
            err = OBJ_ERR_PARAMETER;
         }
      }
      else
      {
         err = OBJ_ERR_PARAMETER;
      }
   }
   else
   {
      err = OBJ_ERR_CONTEXT;
   }
   return err;
}

/* public data ========================================================= */

/* ---------------------------------------------------------------------
   Generated by NEW (c) ED 2.3
   Powered by C-code generator (c) ED 2003 1.0
   --------------------------------------------------------------------- */
