#ifndef _apl_containers_ringbufapi_h_
#define _apl_containers_ringbufapi_h_
/*----------------------------------------------------------------------------
** SUMMARY: Ring buffers (RBUF)
**
** DESCRIPTION:
**  This file provides a collection of interfaces for Ring Buffers.  There
**  are four interfaces based on data type.  
**
**  CAUTION: The ring-buffer handle function arguments are NOT type-safe. The 
**           implementation actually defines the handles as void pointers. This
**           is done because each ring-buffer is/can be different sizes, which 
**           translates to different types. Given the different types, the
**           two choices were 1) require the applicaiton to always cast the
**           handles to a 'generic' ring-buffer handle type; or 2) pass the
**           the handles as void pointers.  Since both approaches are bad
**           with respect to type safety, option 2 was choosen because it
**           is "easier" on the developer.
**
**  USAGE:
**  ------
**  To minimize the RAM/ROM overhead for the ring buffers, some 'tricks' are
**  employed with the buffer definitions and function args.  The following 
**  code snippets show how to define, allocate, and use a 'BYTE' Ring buffer 
**  that can hold at most MAX_KEYS_BUFFERED elements.
**
**      // Define the actual data structure 
**      APL_STRUCTDEF_RBUF8(MyInputKeyBuffer,MAX_KEYS_BUFFERED);  
**      
**      // Allocate an instance of my ring buffer 
**      struct MyInputKeyBuffer keyBuffer;
** 
**      // Initialize the structure
**      Apl_rbuf8Initialize( &keyBuffer, MAX_KEYS_BUFFERED);
**
**      // Add and Get elements from the ring buffer 
**      Apl_rbuf8Add( &keyBuffer, newKeyCode );
**      ...
**      if ( !Apl_rbuf8IsEmpty(&keyBuffer) )
**          {
**          AplByte key = Apl_rbuf8Remove( &keyBuffer );
**          ...
**          }
**
**
** CONFIGURATION 
** -------------
**  COMPILE:     none.
**
**  PLATFORM:    none.
**
**  APPLICATION: The application can override the following types/defintions
**                  AplRBuf8Size    // default is AplByte -->max size:= 255
**                  AplRBuf16Size   // default is AplByte -->max size:= 255
**                  AplRBuf32Size   // default is AplByte -->max size:= 255
**                  AplRBufPSize    // default is AplByte -->max size:= 255
**
**  NOTES:
**  1. For efficency/optimization some methods are 'inlined'.  The inlining
**     is done by using the preprocessor/macros.  The application should
**     treat all methods as function calls and not rely on the fact they may
**     be currently defined as macros.
----------------------------------------------------------------------------*/

#include "apl/types/types.h"        /* For: basic types */

#ifdef __cplusplus
extern "C" {
#endif


/*-------------- MACROS ----------------------------------------------------*/
/** Helper macros for defining a compatible structure for a BYTE Ring buffer 
    of size 'N'. 
 */
#define APL_STRUCTDEF_RBUF8(structName,N)         _APL_STRUCTDEF_RBUF8(structName,N)

/** Helper macro for defining a compatible structure for a 16Bit WORD Ring 
    buffer of size 'N'. 
 */
#define APL_STRUCTDEF_RBUF16(structName,N)        _APL_STRUCTDEF_RBUF16(structName,N)

/** Helper macro for defining a compatible structure for a 32Bit WORD
    buffer of size 'N'. 
 */
#define APL_STRUCTDEF_RBUF32(structName,N)        _APL_STRUCTDEF_RBUF32(structName,N)

/** Helper macro for defining a compatible structure for a POINTER
    buffer of size 'N'. 
 */
#define APL_STRUCTDEF_RBUFP(structName,N)         _APL_STRUCTDEF_RBUFP(structName,N)


/*-------------- TYPES -----------------------------------------------------*/
/** Default max BYTE Ring buffer size to 255 bytes */
#ifndef AplRBuf8Size
#define AplRBuf8Size                    AplByte
#endif

/** Default max 16Bit-WORD Ring buffer size to 255 bytes */
#ifndef AplRBuf16Size
#define AplRBuf16Size                   AplByte
#endif

/** Default max 32Bit-WORD Ring buffer size to 255 bytes */
#ifndef AplRBuf32Size
#define AplRBuf32Size                   AplByte
#endif

/** Default max POINTER Ring buffer size to 255 bytes */
#ifndef AplRBufPSize
#define AplRBufPSize                    AplByte
#endif


/** Handle to a GENERIC BYTE ring buffer */
#define AplRingBuf8Hdl                  struct AplRingBuf8*

/** Handle to a GENERIC 16Bit-WORD ring buffer */
#define AplRingBuf16Hdl                 struct AplRingBuf16*

/** Handle to a GENERIC 32Bit-WORD ring buffer */
#define AplRingBuf32Hdl                 struct AplRingBuf32*

/** Handle to a GENERIC POINTER ring buffer */
#define AplRingBufPHdl                  struct AplRingBufP*



/*-------------- INLINE IMPLEMENTATION -------------------------------------*/
#include "apl/containers/ringbuf.h"           /* For: inline implementation */


/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method initializes the Ring buffer data structure.  This method must 
    be called BEFORE any other operation are called on the buffer. The 
    application must provide an actual ring-buffer INSTANCE (i.e. a reference
    to allocated memory) to the buffer being initialized.
    NOTE:
        o CAUTION: make sure that the size parameter 'maxNumElements' is the
          same value that was used in the 'APL_STRUCTDEF_RBUFxx' statement.

    Prototype:
        void Apl_rbuf8Initialize( AplRingBuf8* rbufToInit, AplRBuf8Size maxNumElements );
 */
#define Apl_rbuf8Initialize                 _Apl_rbuf8Initialize

/** This method appends the specified element to the ring buffer. The
    method return non-zero (true) if added successfully.  Zero (false)
    is returned if the buffer is full (and the element is NOT added).

    Prototype:
        AplBool Apl_rbuf8Add( AplRingBuf8Hdl rbuf, AplByte elementToAdd );
 */
#define Apl_rbuf8Add                        _Apl_rbuf8Add 
    
/** This method returns and removes the first/head element to the ring buffer. 
    This method ASSUMES that the ring buffer is NOT empty.  This requires the
    application to ALWAYS verify that the buffer is not empty before calling
    this method. 

    Prototype:
        AplByte Apl_rbuf8Remove( AplRingBuf8Hdl rbuf );
 */
#define Apl_rbuf8Remove                     _Apl_rbuf8Remove
    
/** This method returns non-zero (true) if the ring buffer is empty.
    
    Prototype:
        AplBool Apl_rbuf8IsEmpty( AplRingBuf8Hdl rbuf );
 */
#define Apl_rbuf8IsEmpty                    _Apl_rbuf8IsEmpty 

/** This method returns non-zero (true) if the ring buffer is full.
    
    Prototype:
        AplBool Apl_rbuf8IsFull( AplRingBuf8Hdl rbuf );
 */
#define Apl_rbuf8IsFull                     _Apl_rbuf8IsFull

/** This method returns maximum number of elements the buffer can hold
    
    Prototype:
        AplRBuf8Size Apl_rbuf8MaxElements( AplRingBuf8Hdl rbuf );
 */
#define Apl_rbuf8MaxElements                _Apl_rbuf8MaxElements

/** This method returns the current number of elements in the buffer. 

    Prototype:
        AplRBuf8Size Apl_rbuf8GetNumElements( AplRingBuf8Hdl rbuf );
 */
#define Apl_rbuf8GetNumElements             _Apl_rbuf8GetNumElements


/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method initializes the Ring buffer data structure.  This method must 
    be called BEFORE any other operation are called on the buffer. The 
    application must provide an actual ring-buffer INSTANCE (i.e. a reference
    to allocated memory) to the buffer being initialized.
    NOTE:
        o CAUTION: make sure that the size parameter 'maxNumElements' is the
          same value that was used in the 'APL_STRUCTDEF_RBUFxx' statement.

    Prototype:
        void Apl_rbuf16Initialize( AplRingBuf16* rbufToInit, AplRBuf16Size maxNumElements );
 */
#define Apl_rbuf16Initialize                _Apl_rbuf16Initialize

/** This method appends the specified element to the ring buffer. The
    method return non-zero (true) if added successfully.  Zero (false)
    is returned if the buffer is full (and the element is NOT added).

    Prototype:
        AplBool Apl_rbuf16Add( AplRingBuf16Hdl rbuf, Apl16u elementToAdd );
 */
#define Apl_rbuf16Add                       _Apl_rbuf16Add 
    
/** This method returns and removes the first/head element to the ring buffer. 
    This method ASSUMES that the ring buffer is NOT empty.  This requires the
    application to ALWAYS verify that the buffer is not empty before calling
    this method. 

    Prototype:
        Apl16u Apl_rbuf16Remove( AplRingBuf16Hdl rbuf );
 */
#define Apl_rbuf16Remove                    _Apl_rbuf16Remove
    
/** This method returns non-zero (true) if the ring buffer is empty.
    
    Prototype:
        AplBool Apl_rbuf16IsEmpty( AplRingBuf16Hdl rbuf );
 */
#define Apl_rbuf16IsEmpty                   _Apl_rbuf16IsEmpty 

/** This method returns non-zero (true) if the ring buffer is full.
    
    Prototype:
        AplBool Apl_rbuf16IsFull( AplRingBuf16Hdl rbuf );
 */
#define Apl_rbuf16IsFull                    _Apl_rbuf16IsFull

/** This method returns maximum number of elements the buffer can hold
    
    Prototype:
        AplRBuf16Size Apl_rbuf16MaxElements( AplRingBuf16Hdl rbuf );
 */
#define Apl_rbuf16MaxElements               _Apl_rbuf16MaxElements

/** This method returns the current number of elements in the buffer. 

    Prototype:
        AplRBuf16Size Apl_rbuf16GetNumElements( AplRingBuf16Hdl rbuf );
 */
#define Apl_rbuf16GetNumElements            _Apl_rbuf16GetNumElements


/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method initializes the Ring buffer data structure.  This method must 
    be called BEFORE any other operation are called on the buffer. The 
    application must provide an actual ring-buffer INSTANCE (i.e. a reference
    to allocated memory) to the buffer being initialized.
    NOTE:
        o CAUTION: make sure that the size parameter 'maxNumElements' is the
          same value that was used in the 'APL_STRUCTDEF_RBUFxx' statement.

    Prototype:
        void Apl_rbuf32Initialize( AplRingBuf32* rbufToInit, AplRBuf32Size maxNumElements );
 */
#define Apl_rbuf32Initialize                _Apl_rbuf32Initialize

/** This method appends the specified element to the ring buffer. The
    method return non-zero (true) if added successfully.  Zero (false)
    is returned if the buffer is full (and the element is NOT added).

    Prototype:
        AplBool Apl_rbuf32Add( AplRingBuf32Hdl rbuf, Apl32u elementToAdd );
 */
#define Apl_rbuf32Add                       _Apl_rbuf32Add 
    
/** This method returns and removes the first/head element to the ring buffer. 
    This method ASSUMES that the ring buffer is NOT empty.  This requires the
    application to ALWAYS verify that the buffer is not empty before calling
    this method. 

    Prototype:
        Apl32u Apl_rbuf32Remove( AplRingBuf32Hdl rbuf );
 */
#define Apl_rbuf32Remove                    _Apl_rbuf32Remove
    
/** This method returns non-zero (true) if the ring buffer is empty.
    
    Prototype:
        AplBool Apl_rbuf32IsEmpty( AplRingBuf32Hdl rbuf );
 */
#define Apl_rbuf32IsEmpty                   _Apl_rbuf32IsEmpty 

/** This method returns non-zero (true) if the ring buffer is full.
    
    Prototype:
        AplBool Apl_rbuf32IsFull( AplRingBuf32Hdl rbuf );
 */
#define Apl_rbuf32IsFull                    _Apl_rbuf32IsFull

/** This method returns maximum number of elements the buffer can hold
    
    Prototype:
        AplRBuf32Size Apl_rbuf32MaxElements( AplRingBuf32Hdl rbuf );
 */
#define Apl_rbuf32MaxElements               _Apl_rbuf32MaxElements

/** This method returns the current number of elements in the buffer. 

    Prototype:
        AplRBuf32Size Apl_rbuf32GetNumElements( AplRingBuf32Hdl rbuf );
 */
#define Apl_rbuf32GetNumElements            _Apl_rbuf32GetNumElements


/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method initializes the Ring buffer data structure.  This method must 
    be called BEFORE any other operation are called on the buffer. The 
    application must provide an actual ring-buffer INSTANCE (i.e. a reference
    to allocated memory) to the buffer being initialized.
    NOTE:
        o CAUTION: make sure that the size parameter 'maxNumElements' is the
          same value that was used in the 'APL_STRUCTDEF_RBUFxx' statement.

    Prototype:
        void Apl_rbufPInitialize( AplRingBufP* rbufToInit, AplRBufPSize maxNumElements );
 */
#define Apl_rbufPInitialize                 _Apl_rbufPInitialize

/** This method appends the specified element to the ring buffer. The
    method return non-zero (true) if added successfully.  Zero (false)
    is returned if the buffer is full (and the element is NOT added).

    Prototype:
        AplBool Apl_rbufPAdd( AplRingBufPHdl rbuf, void* elementToAdd );
 */
#define Apl_rbufPAdd                        _Apl_rbufPAdd 
    
/** This method returns and removes the first/head element to the ring buffer. 
    This method ASSUMES that the ring buffer is NOT empty.  This requires the
    application to ALWAYS verify that the buffer is not empty before calling
    this method. 

    Prototype:
        void* Apl_rbufPRemove( AplRingBufPHdl rbuf );
 */
#define Apl_rbufPRemove                     _Apl_rbufPRemove
    
/** This method returns non-zero (true) if the ring buffer is empty.
    
    Prototype:
        AplBool Apl_rbufPIsEmpty( AplRingBufPHdl rbuf );
 */
#define Apl_rbufPIsEmpty                    _Apl_rbufPIsEmpty 

/** This method returns non-zero (true) if the ring buffer is full.
    
    Prototype:
        AplBool Apl_rbufPIsFull( AplRingBufPHdl rbuf );
 */
#define Apl_rbufPIsFull                     _Apl_rbufPIsFull

/** This method returns maximum number of elements the buffer can hold
    
    Prototype:
        AplRBufPSize Apl_rbufPMaxElements( AplRingBufPHdl rbuf );
 */
#define Apl_rbufPMaxElements                _Apl_rbufPMaxElements

/** This method returns the current number of elements in the buffer. 

    Prototype:
        AplRBufPSize Apl_rbufPGetNumElements( AplRingBufPHdl rbuf );
 */
#define Apl_rbufPGetNumElements             _Apl_rbufPGetNumElements



#ifdef __cplusplus
}
#endif
/*--------------------------------------------------------------------------*/
#endif  /* end _apl_containers_ringbufapi_h_ */

