#ifndef H_ED_RA_20030917140538
#define H_ED_RA_20030917140538

#ifdef __cplusplus
extern "C"
{
#endif

/* ---------------------------------------------------------------------
   (c) ED 2003-2004
   Project      : CLIB
   Function     : Resource Allocator
   Module       : RA
   File         : ra.h
   Created      : 17-09-2003
   Modified     : 23-03-2004
   --------------------------------------------------------------------- */

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

   0.0 17-09-2003 Created
   1.0 17-09-2003 Initial version
   1.1 17-09-2003 Error counters added
   1.2 18-09-2003 Ranges modified:
   .              - Data from 0 to 255
   .              - Resource from 1 to 255. (0 = not allocated or freed)
   1.3 18-09-2003 Interface of ra_free() modified so that the
   .              function updates the resource to RA_RES_FREED.
   1.4 19-09-2003 ra_free_all() added
   1.5 22-09-2003 Return code debug. Compliance with the specs
   2.0 23-09-2003 Redesigned. Resource is now internal only
   2.1 24-09-2003 DBG driven trace added
   2.2 25-09-2003 minimum counter added
   2.3 25-09-2003 The ra_alloc function returns the resource number
   2.4 25-09-2003 Optional identifier added to ra_init()
   2.5 01-10-2003 Ranges modified:
   .              - Data from 0 to 65535
   2.6 07-10-2003 Added function ra_get_free()
   2.7 23-03-2004 Ranges modified:
   .              - Data from 0 to 0xFFFFFFFF

   --------------------------------------------------------------------- */
/* *INDENT-OFF* */
/* ---------------------------------------------------------------------
   Specifications
   --------------

   1 Guidelines

   1.1 The purpose of the RA object is to allocate/free a 'resource' to a
   'data'.

      resource := ALLOCATE (data)

      FREE (resource)

   1.2 Resources

   1.2.1 The resources are allocated from 1 to n
   1.2.1.1 n is programmable from 1 to 255.
   1.2.1.2 The value 0 means 'freed resource'

   1.2.2 The order of allocation is not specified.

   1.2.3 When no more resource is available, no allocation is performed,
         and a specific error code is returned.

   1.2.4 It is the user's responsability to manage the given resources

   1.2.5 Because of the (volontary) limited number of resources, it is
         highly recommended to free a resource that is no longer used.

   1.3 Data

   1.3.1 The data can be any value from 0 to 255.

   1.3.2 When a data is out of range, no allocation is performed, and a
         specific error code is returned.

   2 Operations

   2.1 Initialization

   2.1.1 The initialization can be static or dynamic.
   2.1.1.1 Static operation
   2.1.1.1.1 The initialisation is performed by defining a static
             (or automatic) object of type 'ra_s'.
   2.1.1.1.2 The ra_clr() function is used to clear the object.
   2.1.1.1.3 An array of N ressources of type 'ra_usr_s' must be
             defined. (1 <= N <= 255)

   ra_usr_s array[N];

   2.1.1.1.4 The ra_init() function is used to initialise the object:

   ra_err_e ra_init (ra_s * this
                    , ra_usr_s *p_res
                    , size_t nb_res);

   2.1.2.1 Dynamic operation
   2.1.2.1.1 The initialisation is performed by defining a static
             (or automatic) object of type 'ra_s *'.
   2.1.2.1.2 The ra_create() function is used to create and clear the object.

   ra_s * ra_create (size_t nb_res);

   (1 <= nb_res <= 255)

   2.1.2.1.3 The ra_init() function is used to initialise the object:

   ra_err_e ra_init (ra_s * this
                    , ra_usr_s *p_res
                    , size_t nb_res);

   *WARNING* The p_res parameter must be NULL.
             The nb_res parameter must be 0.

   2.1.2.1.4 The ra_delete() function is used to destroy the object

   2.2 Allocation

   2.2.1 The allocation of a resource is performed by calling the ra_alloc()
     function.

     ra_err_e ra_alloc (ra_s * this, uint data, uchar *p_res);

   2.2.2 Normal operation.

   2.2.2.1 Preconditions.

   2.2.2.1.1 The data must be in range and not have been already allocated.
   2.2.2.1.2 The address of the external ressource (p_res) must be valid.
   2.2.2.1.3 The value of the external resource must be RA_RES_FREED.

   2.2.2.2 A resource number is allocated.

   2.2.2.3 The allocated resource automatically stored at the given address

   2.2.2.4 ra_alloc() returns RA_OK

   2.2.3 Defective operations.

   2.2.3.1 If the data is out of range
   2.2.3.1.1 The error code is RA_ERR_DATA_VALUE
   2.2.3.1.2 No allocation is performed
   2.2.3.1.3 The external resource is unchanged

   2.2.3.2 If the data is already known [1]
   2.2.3.2.1 The error code is RA_ERR_ALREADY_ALLOCATED
   2.2.3.2.2 No allocation is performed
   2.2.3.2.3 The external resource is unchanged

   2.2.3.3 If the external ressource address is invalid
   2.2.3.3.1 The error code is RA_ERR_RESOURCE_ADDRESS
   2.2.3.3.2 No allocation is performed
   2.2.3.3.3 The external resource is unchanged

   2.2.3.4 If the external ressource is not RA_RES_FREED
   2.2.3.4.1 The error code is RA_ERR_RESOURCE_STATUS
   2.2.3.4.2 No allocation is performed
   2.2.3.4.3 The external resource is unchanged

   2.2.3.5 If there is no more ressource
   2.2.3.5.1 The error code is RA_ERR_NO_MORE_RESOURCE
   2.2.3.5.2 No allocation is performed
   2.2.3.5.3 The external resource is unchanged

   2.3 Deallocation

   2.3.2 Normal operation.
   2.3.2.1 Preconditions.
   2.3.2.1.1 The address of the external ressource (p_res) must be valid.
   2.3.2.1.2 The value of the external resource must not be RA_RES_FREED.
   2.3.2.2 The resource is freed.
   2.3.2.3 The value 'RA_RES_FREED' is automatically stored at the given address
   2.3.2.4 ra_free() returns RA_OK

   2.3.3 Defective operations.

   2.3.3.1 If the external ressource address is invalid
   2.3.3.1.1 The error code is RA_ERR_RESOURCE_ADDRESS
   2.3.3.1.2 No deallocation is performed
   2.3.3.1.3 The external resource is unchanged

   2.3.3.2 If the external ressource is RA_RES_FREED
   2.3.3.2.1 The error code is RA_ERR_RESOURCE_STATUS
   2.3.3.2.2 No deallocation is performed
   2.3.3.2.3 The external resource is unchanged

   2.3.3.3 If the ressource is not known
   2.3.3.3.1 The error code is RA_ERR_NEVER_ALLOCATED
   2.3.3.3.2 No deallocation is performed
   2.3.3.3.3 The external resource is forced to RA_RES_FREED

   2.3.3.4 If the ressource is out of range
   2.3.3.4.1 The error code is RA_ERR_RESOURCE_VALUE
   2.3.3.4.2 No allocation is performed
   2.3.3.4.3 The external resource is unchanged

   Notes
   --------------
   [1] The resource must be different. Example:

   uchar res_A;
   uchar res_B;

   ra_alloc (&res, 123, &res_A);
   ra_alloc (&res, 123, &res_B); / * ERROR * /

   --------------------------------------------------------------------- */
/* *INDENT-ON* */



#include <stddef.h>
#include "ed/inc/types.h"

/* macros ============================================================== */

#define RA_OUT 0

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

   enum
   {
      RA_SIZE_MAX = 255,

      RA_dummy
   };

/* The enum range is hold within a int.
 * Can't be bigger than 32767.
 * A qualified macro must be used instead.
 */
#define RA_DATA_MIN 0ul
#define RA_DATA_MAX 0xFFFFFFFFul

   typedef enum
   {
      RA_OK,

#define ITEM(n_, s_)\
   RA_ERR_##n_,

#include "ed/inc/ra_err.itm"

#undef ITEM

      RA_ERR_NB
   }
   ra_err_e;

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

   typedef int ra_out_f (void *p_usr, int data);

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

   typedef struct
   {
      ulong data;               /* 0-FFFFFFFF */
      uint res:8;               /* 1-FF */
      uint used:1;
   }
   ra_usr_s;

   typedef struct
   {
      ra_usr_s *p_res;          /* resources array */
      uint nb_res;              /* resources number */
      uint count;               /* resources counter */
      uint min_count;           /* minimum resources counter */
      struct
      {
         ulong alloc;
         ulong free;
      }
      err;

#if RA_OUT
      ra_out_f *pf;
      void *p_usr;
#endif
      char const *sid;
   }
   ra_s;

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

/* Identification */
   char const *ra_sid (void);
   char const *ra_sver (void);

/* Dynamic constructor / destructor */
   ra_s *ra_create (size_t const nb_res);
   void ra_delete (ra_s * const this);

/* Initialisation */
   ra_err_e ra_clr (ra_s * const this);
   ra_err_e ra_init (ra_s * const this
                     ,ra_usr_s * const p_res
                     ,size_t const nb_res
                     ,char const *sid
   );

#if RA_OUT
   ra_err_e ra_install_out (ra_s * const this
                            ,ra_out_f * const pf
                            ,void *const p_data);
#endif

/* Input functions */
   ra_err_e ra_alloc (ra_s * const this
                      ,ulong const data
                      ,uchar * const p_res);

   ra_err_e ra_free (ra_s * const this, ulong const data);
   ra_err_e ra_free_all (ra_s * const this);

   /* getting data */
   ra_err_e ra_get_data (ra_s * const this
                         ,uchar const res
                         ,ulong * const p_data);

   /* getting resource */
   ra_err_e ra_get_res (ra_s * const this
                        ,uchar * const p_res
                        ,ulong const data);

   /* are they free places */
   ra_err_e ra_get_free (ra_s * const this
                         ,uint * p_free);

#ifdef __cplusplus
}
#endif

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

#endif                          /* guard */
