[嵌入式开发模块]环形缓冲区/循环队列C语言面向对象实现(二)Buffer类源码

介绍见前一篇 https://blog.csdn.net/lin_strong/article/details/88236566

通用类

common.h

#ifndef D_common_H
#define D_common_H

#ifndef BOOL
#define BOOL int
#endif

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

#ifndef NULL
#define NULL 0
#endif

#endif

Container

Container.h

/*
*******************************************************************************************
*
*                                Parent Class for All Container
*
* File : Container.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. Container is defined here as a storage space which hold elements.
*          b. A container has limited capacity(for linked-list,maybe UINT_MAX).
*          c. The capacity may change(e.g. for dynamic-array) according to implementation.
*          d. Container can be 0-capacity, if so, the container is empty and full simultaneously.
*          e. A NULL Container is 0-capacity, 0-count, empty and not-full.
*          f. empty is defined as count == 0.
*          g. full is defined as count >= capacity.
*          h. the class is to be the basic class for all container, so it holds the destroy
*             func.
*******************************************************************************************
*/


#ifndef _CONTAINER_H
#define _CONTAINER_H

#include <stddef.h>
#include <stdint.h>
#include "common.h"

/*
*******************************************************************************************
*                                     DATA TYPE
*******************************************************************************************
*/

typedef struct CONTAINER_STRUCT * Container;

/*
*******************************************************************************************
*                                     INTERFACE
*******************************************************************************************
*/
// return: capacity of the container ct
//         0      when ct == NULL
unsigned int Container_getCapacity(Container ct);
// return: element count of the container ct
//         0      when ct == NULL
unsigned int Container_getCount(Container ct);
// return: whether the container ct is empty
//         TRUE   when ct == NULL
BOOL Container_isEmpty(Container ct);
// return: whether the container ct is full
//         FALSE  when ct == NULL
BOOL Container_isFull(Container ct);
// destroy the container ct
void Container_Destroy(Container ct);

#include "ContainerPrivate.h"

#endif

ContainerPrivate.h

/*
*******************************************************************************************
*
*                                Parent Class for All Container
*
* File : ContainerPrivate.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. this file is only for the developer, user shouldn't use any in this file.
*          b. to inherit from parent class in C:
*
*             #include "ParentClass.h"
*             typedef struct CHILDCLASS_STRUCT{
*               PARENTCLASS_STRUCT parent;
*               SOMETYPE           memberofchild;
*               ...
*             } * ChildClass;
*
*             to use the interface of ParentClass, e.g:
*             
*             ChildClass child = ChildClass_Create();
*             PARENTCLASS_METHOD((ParentClass)child,...);
*          c. developer should implement the whole vtable, none of the interfaces in the
*             vtable can be left NULL. isEmpty and isFull is implemented by calling
*             getCapacity and getCount, so you should implement these two interfaces correctly.
*          d. destroy interface can be left NULL.
*******************************************************************************************
*/
#include "Container.h"

// destroy function signature
typedef void (* OBJECTINTERFACE_VOID)(void * obj);
typedef unsigned int (* CONTAINERINTERFACE_RETURNUINT)(Container ct);

typedef struct CONTAINER_INTERFACE{
  CONTAINERINTERFACE_RETURNUINT   getCapacity;  // return the capacity of the buffer(no need for NULL check)
  CONTAINERINTERFACE_RETURNUINT   getCount;     // return the elements count of the buffer(no need for NULL check)
}CONTAINER_INTERFACE;

typedef const struct CONTAINER_INTERFACE  * CONTAINER_INTERFACE_TABLE;

// members of a container
typedef struct CONTAINER_STRUCT{
  OBJECTINTERFACE_VOID destroy; // destroy method register 
  CONTAINER_INTERFACE_TABLE vtable;
}CONTAINER_STRUCT;

// destroy method member of the container(internal, no NULL check)
#define _Container_fDestroy(ct)         (((Container)(ct))->destroy)
#define _Container_mVtable(ct)          (((Container)(ct))->vtable)
#define _Container_fgetCapacity(ct)        (((Container)(ct))->vtable->getCapacity)
#define _Container_fgetCount(ct)           (((Container)(ct))->vtable->getCount)



// initialize an instance of Container,you should implement all the interface, except for Destroy
//(internal, no NULL check)
// void _Container_Init(Container ct,OBJECTINTERFACE_VOID fDestroy,CONTAINER_INTERFACE_TABLE vtable);
#define _Container_Init(ct,fDestroy,vtable)  \
     {_Container_fDestroy(ct) = fDestroy; \
      _Container_mVtable(ct)  = vtable;}

// get the capacity of the container(internal, no NULL check)
unsigned int _Container_getCapacity(Container ct);
// get the count of the container(internal, no NULL check)
unsigned int _Container_getCount(Container ct);
// whether the container ct is empty(internal, no NULL check)
BOOL _Container_isEmpty(Container ct);
// whether the container ct is full(internal, no NULL check)
BOOL _Container_isFull(Container ct);

BOOL _Container_isNullorEmpty(Container ct);
BOOL _Container_isNullorFull(Container ct);

// and simple destroyer prepared for those who just need to call free(obj)
void _Destroy_JustCallFree(void * obj);

Container.c

/*
*******************************************************************************************
*
*                           Interface Implementation for All Container
*
* File : Container.c
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): 
*******************************************************************************************
*/
#include <stdlib.h>
#include "Container.h"
// void _Container_Init(Container ct,OBJECTINTERFACE_VOID fDestroy,CONTAINER_INTERFACE_TABLE vtable){
//   ct->destroy = fDestroy;
//   ct->vtable  = vtable;
// }

unsigned int Container_getCapacity(Container ct){
  if(ct)
    return _Container_getCapacity(ct);
  return 0;
}

unsigned int Container_getCount(Container ct){
  if(ct)
    return _Container_getCount(ct);
  return 0;
}

BOOL Container_isEmpty(Container ct){
  if(ct)
    return _Container_isEmpty(ct);
  return TRUE;
}

BOOL Container_isFull(Container ct){
  if(ct)
    return _Container_isFull(ct);
  return FALSE;
}

void Container_Destroy(Container ct){
  if(ct && ct->destroy)
    ct->destroy(ct);
}

unsigned int _Container_getCapacity(Container ct){
  return _Container_fgetCapacity(ct)(ct);
}
unsigned int _Container_getCount(Container ct){
  return _Container_fgetCount(ct)(ct);
}
BOOL _Container_isEmpty(Container ct){
  return _Container_getCount(ct) == 0;
}
BOOL _Container_isFull(Container ct){
  return _Container_getCount(ct) >= _Container_getCapacity(ct);
}

BOOL _Container_isNullorEmpty(Container ct){
  return ct == NULL || _Container_isEmpty(ct);
}
BOOL _Container_isNullorFull(Container ct){
  return ct == NULL || _Container_isFull(ct);
}

void _Destroy_JustCallFree(void * buf){
  if(buf == NULL)
    return;
  free(buf);
}

Buffer

Buffer.h

/*
*******************************************************************************************
*
*                                Parent Class for All Buffer
*
* File : Buffer.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. Buffer is defined here as a double-ended container, which has a front element
*             and a back element, and is able to insert and remove element at front and back.
*******************************************************************************************
*/

#ifndef _BUFFER_H
#define _BUFFER_H

#include "Container.h"

/*
*******************************************************************************************
*                                        DATA TYPE
*******************************************************************************************
*/

typedef struct BUFFER_STRUCT        * Buffer;
typedef struct BUFFERUINT8_STRUCT   * BufferUINT8;
typedef struct BUFFERUINT16_STRUCT  * BufferUINT16;
typedef struct BUFFERUINT32_STRUCT  * BufferUINT32;

typedef void (* BUFFERINTERFACE_VOID)(Buffer);
typedef void (* BUFFERUINT8INTERFACE_VOID)(BufferUINT8);
typedef void (* BUFFERUINT16INTERFACE_VOID)(BufferUINT16);
typedef void (* BUFFERUINT32INTERFACE_VOID)(BufferUINT32);

typedef void (* BUFFERUINT8INTERFACE_TAKEELEMENT)(BufferUINT8,uint8_t);
typedef void (* BUFFERUINT16INTERFACE_TAKEELEMENT)(BufferUINT16,uint16_t);
typedef void (* BUFFERUINT32INTERFACE_TAKEELEMENT)(BufferUINT32,uint32_t);

typedef uint8_t (* BUFFERUINT8INTERFACE_RETURNELEMENT)(BufferUINT8);
typedef uint16_t (* BUFFERUINT16INTERFACE_RETURNELEMENT)(BufferUINT16);
typedef uint32_t (* BUFFERUINT32INTERFACE_RETURNELEMENT)(BufferUINT32);
/*
*******************************************************************************************
*                                       CONSTANT
*******************************************************************************************
*/

#define BUFFER_WHENERR_ELEMENTRETURN       -1

/*
*******************************************************************************************
*                               INTERFACE FOR ALL BUFFER CLASS
*******************************************************************************************
*/

// unsigned int Buffer_getCapacity(Buffer buf);
// return: capacity of the Buffer buf
//         0      when buf == NULL
#define Buffer_getCapacity(buf)              Container_getCapacity((Container)(buf))
// unsigned int Buffer_getCount(Buffer buf);
// return: element count of the Buffer buf
//         0      when buf == NULL
#define Buffer_getCount(buf)                 Container_getCount((Container)(buf))
// BOOL Buffer_isEmpty(Buffer buf);
// return: whether the Buffer buf is empty
//         TRUE   when buf == NULL
#define Buffer_isEmpty(buf)                  Container_isEmpty((Container)(buf))
// BOOL Buffer_isFull(Buffer buf);
// return: whether the Buffer buf is full
//         FALSE  when buf == NULL
#define Buffer_isFull(buf)                   Container_isFull((Container)(buf))
// void Buffer_Destroy(Buffer buf);
// destroy the Buffer buf
#define Buffer_Destroy(buf)                  Container_Destroy((Container)(buf))
// cleanup the Buffer buf
void Buffer_Cleanup(Buffer buf);
/*
*******************************************************************************************
*                              INTERFACE FOR UINT8 BUFFER
*******************************************************************************************
*/

// unsigned int BufferUINT8_getCapacity(BufferUINT8 buf);
#define BufferUINT8_getCapacity(buf)          Buffer_getCapacity((Buffer)buf)
// unsigned int BufferUINT8_geyCount(BufferUINT8 buf);
#define BufferUINT8_getCount(buf)             Buffer_getCount((Buffer)buf)
// BOOL BufferUINT8_isEmpty(BufferUINT8 buf);
#define BufferUINT8_isEmpty(buf)              Buffer_isEmpty((Buffer)buf)
// BOOL BufferUINT8_isFull(BufferUINT8 buf);
#define BufferUINT8_isFull(buf)               Buffer_isFull((Buffer)buf)
// void BufferUINT8_Destroy(BufferUINT8 buf);
#define BufferUINT8_Destroy(buf)              Buffer_Destroy((Buffer)buf)
// return the front element while the element still in the buffer.
// return BUFFER_WHENERR_ELEMENTRETURN when any error
uint8_t BufferUINT8_Front   (BufferUINT8 buf);
// return the back element while the element still in the buffer.
// return BUFFER_WHENERR_ELEMENTRETURN when any error
uint8_t BufferUINT8_Back    (BufferUINT8 buf);
// put an element at the front of the buffer.
// if container is full, the behavior depends on the implementation.
void    BufferUINT8_FrontIn (BufferUINT8 buf,uint8_t element);
// put an element at the back of the buffer.
// if container is full, the behavior depends on the implementation.
void    BufferUINT8_BackIn  (BufferUINT8 buf,uint8_t element);
// pick an element from the front of the buffer.
// return BUFFER_WHENERR_ELEMENTRETURN when any error
uint8_t BufferUINT8_FrontOut(BufferUINT8 buf);
// pick an element from the back of the buffer.
// return BUFFER_WHENERR_ELEMENTRETURN when any error
uint8_t BufferUINT8_BackOut (BufferUINT8 buf);
// void BufferUINT8_Cleanup(BufferUINT8 buf);
// cleanup the Buffer buf
#define BufferUINT8_Cleanup(buf)             Buffer_Cleanup((Buffer)buf)
/*
*******************************************************************************************
*                               INTERFACE FOR UINT16 BUFFER
*******************************************************************************************
*/
// unsigned int BufferUINT16_getCapacity(BufferUINT16 buf);
#define BufferUINT16_getCapacity(buf)          Buffer_getCapacity((Buffer)buf)
// unsigned int BufferUINT16_getCount(BufferUINT16 buf);
#define BufferUINT16_getCount(buf)             Buffer_getCount((Buffer)buf)
// BOOL BufferUINT16_isEmpty(BufferUINT16 buf);
#define BufferUINT16_isEmpty(buf)              Buffer_isEmpty((Buffer)buf)
// BOOL BufferUINT16_isFull(BufferUINT16 buf);
#define BufferUINT16_isFull(buf)               Buffer_isFull((Buffer)buf)
// void BufferUINT16_Destroy(BufferUINT16 buf);
#define BufferUINT16_Destroy(buf)              Buffer_Destroy((Buffer)buf)
// return the front element while the element still in the buffer.
// return BUFFER_WHENERR_ELEMENTRETURN when any error
uint16_t BufferUINT16_Front   (BufferUINT16 buf);
// return the back element while the element still in the buffer.
// return BUFFER_WHENERR_ELEMENTRETURN when any error
uint16_t BufferUINT16_Back    (BufferUINT16 buf);
// put an element at the front of the buffer.
// if container is full, the behavior depends on the implementation.
void    BufferUINT16_FrontIn (BufferUINT16 buf,uint16_t element);
// put an element at the back of the buffer.
// if container is full, the behavior depends on the implementation.
void    BufferUINT16_BackIn  (BufferUINT16 buf,uint16_t element);
// pick an element from the front of the buffer.
// return BUFFER_WHENERR_ELEMENTRETURN when any error
uint16_t BufferUINT16_FrontOut(BufferUINT16 buf);
// pick an element from the back of the buffer.
// return BUFFER_WHENERR_ELEMENTRETURN when any error
uint16_t BufferUINT16_BackOut (BufferUINT16 buf);
// void BufferUINT16_Cleanup(BufferUINT16 buf);
// cleanup the Buffer buf
#define BufferUINT16_Cleanup(buf)             Buffer_Cleanup((Buffer)buf)

/*
*******************************************************************************************
*                               INTERFACE FOR UINT32 BUFFER
*******************************************************************************************
*/
// unsigned int BufferUINT32_getCapacity(BufferUINT32 buf);
#define BufferUINT32_getCapacity(buf)          Buffer_getCapacity((Buffer)buf)
// unsigned int BufferUINT32_getCount(BufferUINT32 buf);
#define BufferUINT32_getCount(buf)             Buffer_getCount((Buffer)buf)
// BOOL BufferUINT32_isEmpty(BufferUINT32 buf);
#define BufferUINT32_isEmpty(buf)              Buffer_isEmpty((Buffer)buf)
// BOOL BufferUINT32_isFull(BufferUINT32 buf);
#define BufferUINT32_isFull(buf)               Buffer_isFull((Buffer)buf)
// void BufferUINT32_Destroy(BufferUINT32 buf);
#define BufferUINT32_Destroy(buf)              Buffer_Destroy((Buffer)buf)
// return the front element while the element still in the buffer.
// return BUFFER_WHENERR_ELEMENTRETURN when any error
uint32_t BufferUINT32_Front   (BufferUINT32 buf);
// return the back element while the element still in the buffer.
// return BUFFER_WHENERR_ELEMENTRETURN when any error
uint32_t BufferUINT32_Back    (BufferUINT32 buf);
// put an element at the front of the buffer.
// if container is full, the behavior depends on the implementation.
void    BufferUINT32_FrontIn (BufferUINT32 buf,uint32_t element);
// put an element at the back of the buffer.
// if container is full, the behavior depends on the implementation.
void    BufferUINT32_BackIn  (BufferUINT32 buf,uint32_t element);
// pick an element from the front of the buffer.
// return BUFFER_WHENERR_ELEMENTRETURN when any error
uint32_t BufferUINT32_FrontOut(BufferUINT32 buf);
// pick an element from the back of the buffer.
// return BUFFER_WHENERR_ELEMENTRETURN when any error
uint32_t BufferUINT32_BackOut (BufferUINT32 buf);
// void BufferUINT32_Cleanup(BufferUINT32 buf);
// cleanup the Buffer buf
#define BufferUINT32_Cleanup(buf)             Buffer_Cleanup((Buffer)buf)

#include "BufferPrivate.h"
#endif

BufferPrivate.h

/*
*******************************************************************************************
*
*                                Parent Class for All Buffer
*
* File : BufferPrivate.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. this file is only for the developer, user shouldn't use any in this file.
*          b. to inherit from parent class in C:
*
*             #include "ParentClass.h"
*             typedef struct CHILDCLASS_STRUCT{
*               PARENTCLASS_STRUCT parent;
*               SOMETYPE           memberofchild;
*               ...
*             } * ChildClass;
*
*             to use the interface of ParentClass, e.g:
*             
*             ChildClass child = ChildClass_Create();
*             PARENTCLASS_METHOD((ParentClass)child,...);
*
*          c. Main purpose of this class is to provide common interface for Buffer of all 
*             type. All Buffer Objects have the same shape interfaces (in the virtual 
*             table) following the exact same order below:
*             
*             ElementType BufferXXXX_Front   (Buffer buf);
*             ElementType BufferXXXX_Back    (Buffer buf);
*             void        BufferXXXX_FrontIn (Buffer buf,ElementType element);
*             void        BufferXXXX_BackIn  (Buffer buf,ElementType element);
*             ElementType BufferXXXX_FrontIn (Buffer buf);
*             ElementType BufferXXXX_BackOut (Buffer buf);
*             void        BufferXXXX_Cleanup (Buffer buf);
* 
*             Different ElementTypes lead to different function signatures, however, due to
*             the exact same order, we know which one is the "front" function of all function.
*          d. If you want to add a Buffer Class of new ElementType, you need to implement
*             some methods to guide compiler to correct function signatures, just like 
*                     uint8_t BufferUINT8_Front(BufferUINT8 buf);
*             do. You can use Implementations of BufferUINT8 Interface as a template to
*             create yours.
*          e. If you want to write an implementation for BufferUINT8 Class, for example. 
*             the main work you should do is to inherit from the Buffer Class, implement
*             the CONTAINER_INTERFACE and BUFFER_INTERFACE. And when creating the instance,
*             assign the virtual table.
*             Then, when user call the interface, the corresponding interface will be called,
*             there is no need for NULL check in your interface implementation.
*          f. To reduce redundancy, it's recommended to adapt from the exist Buffer Class,
*             whose element type take the same space as your new type, rather than create 
*             interfaces for new type. e.g,BufferChar can be adapted from BufferUINT8.
*          g. developer should implement the whole vtable, none of the interfaces in the
*             vtable can be left NULL. There will be no NULL check for vtable.
*          h. !!! the manners of front, back, frontOut and backOut when buffer is empty,!!!
*             !!! and of frontIn and frontOut when buffer is full, are not defined.     !!!
*******************************************************************************************
*/

#include "Buffer.h"

/*
*******************************************************************************************
*                                  PROTECTED   INTERFACES
*******************************************************************************************
*/
typedef const struct BUFFER_INTERFACE       * BUFFER_INTERFACE_TABLE;
typedef const struct BUFFERUINT8_INTERFACE  * BUFFERUINT8_INTERFACE_TABLE;
typedef const struct BUFFERUINT16_INTERFACE * BUFFERUINT16_INTERFACE_TABLE;
typedef const struct BUFFERUINT32_INTERFACE * BUFFERUINT32_INTERFACE_TABLE;

typedef struct BUFFER_STRUCT{
  CONTAINER_STRUCT parent;
  union{
    BUFFER_INTERFACE_TABLE       v;
    BUFFERUINT8_INTERFACE_TABLE  uint8;
    BUFFERUINT16_INTERFACE_TABLE uint16;
    BUFFERUINT32_INTERFACE_TABLE uint32;
  } vtable;
}BUFFER_STRUCT;

#define _Buffer_mVtable(buf)         (((Buffer)(buf))->vtable.v)
#define _Buffer_fFront(buf)          (_Buffer_mVtable(buf)->front)
#define _Buffer_fBack(buf)           (_Buffer_mVtable(buf)->back)
#define _Buffer_fFrontIn(buf)        (_Buffer_mVtable(buf)->frontIn)
#define _Buffer_fBackIn(buf)         (_Buffer_mVtable(buf)->backIn)
#define _Buffer_fFrontOut(buf)       (_Buffer_mVtable(buf)->frontOut)
#define _Buffer_fBackOut(buf)        (_Buffer_mVtable(buf)->backOut)
#define _Buffer_fCleanup(buf)        (_Buffer_mVtable(buf)->cleanup)

typedef struct  BUFFERUINT8_STRUCT{
  BUFFER_STRUCT member;
}BUFFERUINT8_STRUCT;

#define _BufferUINT8_mVtable(buf)         (((Buffer)(buf))->vtable.uint8)
#define _BufferUINT8_fFront(buf)          (_BufferUINT8_mVtable(buf)->front)
#define _BufferUINT8_fBack(buf)           (_BufferUINT8_mVtable(buf)->back)
#define _BufferUINT8_fFrontIn(buf)        (_BufferUINT8_mVtable(buf)->frontIn)
#define _BufferUINT8_fBackIn(buf)         (_BufferUINT8_mVtable(buf)->backIn)
#define _BufferUINT8_fFrontOut(buf)       (_BufferUINT8_mVtable(buf)->frontOut)
#define _BufferUINT8_fBackOut(buf)        (_BufferUINT8_mVtable(buf)->backOut)
#define _BufferUINT8_fCleanup(buf)        (_BufferUINT8_mVtable(buf)->cleanup)

typedef struct  BUFFERUINT16_STRUCT{
  BUFFER_STRUCT member;
}BUFFERUINT16_STRUCT;

#define _BufferUINT16_mVtable(buf)        (((Buffer)(buf))->vtable.uint16)
#define _BufferUINT16_fFront(buf)         (_BufferUINT16_mVtable(buf)->front)
#define _BufferUINT16_fBack(buf)          (_BufferUINT16_mVtable(buf)->back)
#define _BufferUINT16_fFrontIn(buf)       (_BufferUINT16_mVtable(buf)->frontIn)
#define _BufferUINT16_fBackIn(buf)        (_BufferUINT16_mVtable(buf)->backIn)
#define _BufferUINT16_fFrontOut(buf)      (_BufferUINT16_mVtable(buf)->frontOut)
#define _BufferUINT16_fBackOut(buf)       (_BufferUINT16_mVtable(buf)->backOut)
#define _BufferUINT16_fCleanup(buf)       (_BufferUINT16_mVtable(buf)->cleanup)

typedef struct  BUFFERUINT32_STRUCT{
  BUFFER_STRUCT member;
}BUFFERUINT32_STRUCT;

#define _BufferUINT32_mVtable(buf)        (((Buffer)(buf))->vtable.uint32)
#define _BufferUINT32_fFront(buf)         (_BufferUINT32_mVtable(buf)->front)
#define _BufferUINT32_fBack(buf)          (_BufferUINT32_mVtable(buf)->back)
#define _BufferUINT32_fFrontIn(buf)       (_BufferUINT32_mVtable(buf)->frontIn)
#define _BufferUINT32_fBackIn(buf)        (_BufferUINT32_mVtable(buf)->backIn)
#define _BufferUINT32_fFrontOut(buf)      (_BufferUINT32_mVtable(buf)->frontOut)
#define _BufferUINT32_fBackOut(buf)       (_BufferUINT32_mVtable(buf)->backOut)
#define _BufferUINT32_fCleanup(buf)       (_BufferUINT32_mVtable(buf)->cleanup)

typedef void (* BUFFERINTERFACE_POINTER)(void);
typedef struct BUFFER_INTERFACE{
  BUFFERINTERFACE_POINTER   front;       // the buf passed in is assured not NULL
  BUFFERINTERFACE_POINTER   back;        // the buf passed in is assured not NULL
  BUFFERINTERFACE_POINTER   frontIn;     // the buf passed in is assured not NULL
  BUFFERINTERFACE_POINTER   backIn;      // the buf passed in is assured not NULL
  BUFFERINTERFACE_POINTER   frontOut;    // the buf passed in is assured not NULL
  BUFFERINTERFACE_POINTER   backOut;     // the buf passed in is assured not NULL
  BUFFERINTERFACE_VOID      cleanup;     // the buf passed in is assured not NULL
}BUFFER_INTERFACE;


// if don't implement any interface, just leave it NULL
typedef struct BUFFERUINT8_INTERFACE{
  BUFFERUINT8INTERFACE_RETURNELEMENT  front;    // the buf passed in is assured not NULL
  BUFFERUINT8INTERFACE_RETURNELEMENT  back;     // the buf passed in is assured not NULL
  BUFFERUINT8INTERFACE_TAKEELEMENT    frontIn;  // the buf passed in is assured not NULL
  BUFFERUINT8INTERFACE_TAKEELEMENT    backIn;   // the buf passed in is assured not NULL
  BUFFERUINT8INTERFACE_RETURNELEMENT  frontOut; // the buf passed in is assured not NULL
  BUFFERUINT8INTERFACE_RETURNELEMENT  backOut;  // the buf passed in is assured not NULL
  BUFFERUINT8INTERFACE_VOID           cleanup;  // the buf passed in is assured not NULL
}BUFFERUINT8_INTERFACE;

// if don't implement any interface, just leave it NULL
typedef struct BUFFERUINT16_INTERFACE{
  BUFFERUINT16INTERFACE_RETURNELEMENT  front;    // the buf passed in is assured not NULL
  BUFFERUINT16INTERFACE_RETURNELEMENT  back;     // the buf passed in is assured not NULL
  BUFFERUINT16INTERFACE_TAKEELEMENT    frontIn;  // the buf passed in is assured not NULL
  BUFFERUINT16INTERFACE_TAKEELEMENT    backIn;   // the buf passed in is assured not NULL
  BUFFERUINT16INTERFACE_RETURNELEMENT  frontOut; // the buf passed in is assured not NULL
  BUFFERUINT16INTERFACE_RETURNELEMENT  backOut;  // the buf passed in is assured not NULL
  BUFFERUINT16INTERFACE_VOID           cleanup;  // the buf passed in is assured not NULL
}BUFFERUINT16_INTERFACE;

typedef struct BUFFERUINT32_INTERFACE{
  BUFFERUINT32INTERFACE_RETURNELEMENT  front;    // the buf passed in is assured not NULL
  BUFFERUINT32INTERFACE_RETURNELEMENT  back;     // the buf passed in is assured not NULL
  BUFFERUINT32INTERFACE_TAKEELEMENT    frontIn;  // the buf passed in is assured not NULL
  BUFFERUINT32INTERFACE_TAKEELEMENT    backIn;   // the buf passed in is assured not NULL
  BUFFERUINT32INTERFACE_RETURNELEMENT  frontOut; // the buf passed in is assured not NULL
  BUFFERUINT32INTERFACE_RETURNELEMENT  backOut;  // the buf passed in is assured not NULL
  BUFFERUINT32INTERFACE_VOID           cleanup;  // the buf passed in is assured not NULL
}BUFFERUINT32_INTERFACE;

/*
*******************************************************************************************
*                            PROTECTED  MEMBER  AND  METHOD
*******************************************************************************************
*/
// initialize a Buffer instance(internal, no NULL check)
// void _Buffer_Init(Buffer buf,OBJECTINTERFACE_VOID fDestroy,CONTAINER_INTERFACE_TABLE c_vtable,
//                  BUFFER_INTERFACE_TABLE vtable);
#define _Buffer_Init(buf,fDestroy,c_vtable,vtable)  \
    { _Container_Init(buf,fDestroy,c_vtable); \
      _Buffer_mVtable(buf) = vtable; }
// destroy method member of the buffer(internal, no NULL check)
#define _Buffer_fDestroy(buf)         (_Container_fDestroy((Container)(buf)))
#define _Buffer_getCapacity(buf)      _Container_getCapacity((Container)(buf))
#define _Buffer_getCount(buf)         _Container_getCount((Container)(buf))
// whether the buffer is empty(internal, no NULL check)
#define _Buffer_isEmpty(buf)          _Container_isEmpty((Container)(buf))
// whether the buffer is full(internal, no NULL check)
#define _Buffer_isFull(buf)           _Container_isFull((Container)(buf))

//BOOL _Buffer_isNullorEmpty(Buffer buf);
#define _Buffer_isNullorEmpty(buf)    _Container_isNullorEmpty((Container)(buf))
//BOOL _Buffer_isNullorFull(Buffer buf);
#define _Buffer_isNullorFull(buf)     _Container_isNullorFull((Container)(buf))

/*
*******************************************************************************************
*                              PROTECTED   INTERFACE   METHODS
*******************************************************************************************
*/

// offset of each interface in the vtable
#define _BufferInterface_offset_Front             0
#define _BufferInterface_offset_Back              1
#define _BufferInterface_offset_FrontIn           2
#define _BufferInterface_offset_BackIn            3
#define _BufferInterface_offset_FrontOut          4
#define _BufferInterface_offset_BackOut           5
#define _BufferInterface_offset_Cleanup           6

#define _BufferInterface_byOffset(buf,offset)     \
  (((BUFFERINTERFACE_POINTER *)_Buffer_mVtable(buf))[offset])
// will check whether buf is NULL , whether buf->vtable is NULL
BUFFERINTERFACE_POINTER _BufferInterface_getByOffset(Buffer buf,unsigned int offset);
BUFFERINTERFACE_POINTER _BufferInterface_getByOffsetIfCanReturnElement(Buffer buf,unsigned int offset);
BUFFERINTERFACE_POINTER _BufferInterface_getByOffsetIfCanTakeElement(Buffer buf,unsigned int offset);

Buffer.c

/*
*******************************************************************************************
*
*    Common Methods for All Buffer Class and implementations for UINT8, UINT16, UINT32
*
* File : Buffer.c
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): 
*******************************************************************************************
*/

#include "Buffer.h"

// void _Buffer_Init(Buffer buf,OBJECTINTERFACE_VOID fDestroy,CONTAINER_INTERFACE_TABLE c_vtable,
//   BUFFER_INTERFACE_TABLE vtable){
//   _Container_Init((Container)buf,(OBJECTINTERFACE_VOID)fDestroy,c_vtable);
//   _Buffer_mVtable(buf) = vtable;
// }

void Buffer_Cleanup(Buffer buf){
  BUFFERINTERFACE_VOID _interface;
  if(buf == NULL)
    return;
  _interface = (BUFFERINTERFACE_VOID)_BufferInterface_getByOffset(buf,_BufferInterface_offset_Cleanup);
  _interface(buf);
}

BUFFERINTERFACE_POINTER _BufferInterface_getByOffset(Buffer buf,unsigned int offset){
//  if(buf && _Buffer_mVtable(buf))    we assume every buffer should implement the (whole) vtable.
  return _BufferInterface_byOffset(buf,offset);
}

BUFFERINTERFACE_POINTER _BufferInterface_getByOffsetIfCanTakeElement(Buffer buf,unsigned int offset){
  if(!_Buffer_isFull(buf))
    return _BufferInterface_getByOffset(buf,offset);
  return NULL;
}

BUFFERINTERFACE_POINTER _BufferInterface_getByOffsetIfCanReturnElement(Buffer buf,unsigned int offset){
  if(!_Buffer_isEmpty(buf))
    return _BufferInterface_getByOffset(buf,offset);
  return NULL;
}

static uint8_t BufferUINT8Interface_ReturnElement(BufferUINT8 buf,unsigned int offset){
  BUFFERUINT8INTERFACE_RETURNELEMENT _interface;
  if(buf == NULL)
    return BUFFER_WHENERR_ELEMENTRETURN;
  _interface = (BUFFERUINT8INTERFACE_RETURNELEMENT)_BufferInterface_getByOffset((Buffer)buf,offset);
  return _interface(buf);
}

static void BufferUINT8Interface_TakeElement(BufferUINT8 buf,unsigned int offset,uint8_t element){
  BUFFERUINT8INTERFACE_TAKEELEMENT _interface;
  if(buf == NULL)
    return;
  _interface = (BUFFERUINT8INTERFACE_TAKEELEMENT)_BufferInterface_getByOffset((Buffer)buf,offset);
  _interface(buf,element);
}

uint8_t BufferUINT8_Front(BufferUINT8 buf){
  return BufferUINT8Interface_ReturnElement(buf,_BufferInterface_offset_Front);
}

uint8_t BufferUINT8_Back(BufferUINT8 buf){
  return BufferUINT8Interface_ReturnElement(buf,_BufferInterface_offset_Back);
}

void BufferUINT8_FrontIn(BufferUINT8 buf,uint8_t element){
  BufferUINT8Interface_TakeElement(buf,_BufferInterface_offset_FrontIn,element);
}

void BufferUINT8_BackIn(BufferUINT8 buf,uint8_t element){
  BufferUINT8Interface_TakeElement(buf,_BufferInterface_offset_BackIn,element);
}

uint8_t BufferUINT8_FrontOut(BufferUINT8 buf){
  return BufferUINT8Interface_ReturnElement(buf,_BufferInterface_offset_FrontOut);
}

uint8_t BufferUINT8_BackOut(BufferUINT8 buf){
  return BufferUINT8Interface_ReturnElement(buf,_BufferInterface_offset_BackOut);
}

static uint16_t BufferUINT16Interface_ReturnElement(BufferUINT16 buf,unsigned int offset){
  BUFFERUINT16INTERFACE_RETURNELEMENT _interface;
  if(buf == NULL)
    return BUFFER_WHENERR_ELEMENTRETURN;
  _interface = (BUFFERUINT16INTERFACE_RETURNELEMENT)_BufferInterface_getByOffset((Buffer)buf,offset);
  return _interface(buf);
}

static void BufferUINT16Interface_TakeElement(BufferUINT16 buf,unsigned int offset,uint16_t element){
  BUFFERUINT16INTERFACE_TAKEELEMENT _interface;
  if(buf == NULL)
    return;
  _interface = (BUFFERUINT16INTERFACE_TAKEELEMENT)_BufferInterface_getByOffset((Buffer)buf,offset);
  _interface(buf,element);
}

uint16_t BufferUINT16_Front(BufferUINT16 buf){
  return BufferUINT16Interface_ReturnElement(buf,_BufferInterface_offset_Front);
}

uint16_t BufferUINT16_Back(BufferUINT16 buf){
  return BufferUINT16Interface_ReturnElement(buf,_BufferInterface_offset_Back);
}

void BufferUINT16_FrontIn(BufferUINT16 buf,uint16_t element){
  BufferUINT16Interface_TakeElement(buf,_BufferInterface_offset_FrontIn,element);
}

void BufferUINT16_BackIn(BufferUINT16 buf,uint16_t element){
  BufferUINT16Interface_TakeElement(buf,_BufferInterface_offset_BackIn,element);
}

uint16_t BufferUINT16_FrontOut(BufferUINT16 buf){
  return BufferUINT16Interface_ReturnElement(buf,_BufferInterface_offset_FrontOut);
}

uint16_t BufferUINT16_BackOut(BufferUINT16 buf){
  return BufferUINT16Interface_ReturnElement(buf,_BufferInterface_offset_BackOut);
}

static uint32_t BufferUINT32Interface_ReturnElement(BufferUINT32 buf,unsigned int offset){
  BUFFERUINT32INTERFACE_RETURNELEMENT _interface;
  if(buf == NULL)
    return BUFFER_WHENERR_ELEMENTRETURN;
  _interface = (BUFFERUINT32INTERFACE_RETURNELEMENT)_BufferInterface_getByOffset((Buffer)buf,offset);
  return _interface(buf);
}

static void BufferUINT32Interface_TakeElement(BufferUINT32 buf,unsigned int offset,uint32_t element){
  BUFFERUINT32INTERFACE_TAKEELEMENT _interface;
  if(buf == NULL)
    return;
  _interface = (BUFFERUINT32INTERFACE_TAKEELEMENT)_BufferInterface_getByOffset((Buffer)buf,offset);
  _interface(buf,element);
}

uint32_t BufferUINT32_Front(BufferUINT32 buf){
  return BufferUINT32Interface_ReturnElement(buf,_BufferInterface_offset_Front);
}

uint32_t BufferUINT32_Back(BufferUINT32 buf){
  return BufferUINT32Interface_ReturnElement(buf,_BufferInterface_offset_Back);
}

void BufferUINT32_FrontIn(BufferUINT32 buf,uint32_t element){
  BufferUINT32Interface_TakeElement(buf,_BufferInterface_offset_FrontIn,element);
}

void BufferUINT32_BackIn(BufferUINT32 buf,uint32_t element){
  BufferUINT32Interface_TakeElement(buf,_BufferInterface_offset_BackIn,element);
}

uint32_t BufferUINT32_FrontOut(BufferUINT32 buf){
  return BufferUINT32Interface_ReturnElement(buf,_BufferInterface_offset_FrontOut);
}

uint32_t BufferUINT32_BackOut(BufferUINT32 buf){
  return BufferUINT32Interface_ReturnElement(buf,_BufferInterface_offset_BackOut);
}

BufferIndexed

BufferIndexed.h

/*
*******************************************************************************************
*
*                              Parent Class for All Indexed Buffer
*
* File : BufferIndexed.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. Indexed Buffer is defined here as a buffer whose element can be accessed by index.
*          b. Index here is 0-based, 0-index element is the front element, 1-index element
*             is the second-front element, and so on; the count-1 element is the back element.
*          c. For a BufferIndexed instance, for example, an BufferUINT8Indexed instance.you can:
*                    // assign 30 to the second element in the buffer
*                       BufferUINT8Indexed_set(buf,1,30);
*                    // get the value of the second element in the buffer(still in the buffer)
*                       i = BufferUINT8Indexed_get(buf,1);
*             you need to make sure the index between 0 and count-1.
*******************************************************************************************
*/
#ifndef _BUFFERINDEXED_H
#define _BUFFERINDEXED_H

#include "Buffer.h"

typedef struct BUFFERINDEXED_STRUCT
  * BufferIndexed,
  * BufferUINT8Indexed,
  * BufferUINT16Indexed,
  * BufferUINT32Indexed;

// user should make sure that index between 0 and count - 1, or bad thing may happen.
void BufferUINT8Indexed_set (BufferUINT8Indexed buf,unsigned int index,uint8_t element);
uint8_t BufferUINT8Indexed_get(BufferUINT8Indexed buf,unsigned int index);
void BufferUINT16Indexed_set(BufferUINT16Indexed buf,unsigned int index,uint16_t element);
uint16_t BufferUINT16Indexed_get(BufferUINT16Indexed buf,unsigned int index);
void BufferUINT32Indexed_set(BufferUINT32Indexed buf,unsigned int index,uint32_t element);
uint32_t BufferUINT32Indexed_get(BufferUINT32Indexed buf,unsigned int index);

#include "BufferIndexedPrivate.h"
#endif

BufferIndexedPrivate.h

/*
*******************************************************************************************
*
*                  Parent Class for All Indexed Array Buffer
*
* File : BufferIndexedPrivate.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. this file is only for the developer, user shouldn't use any in this file.
*          b. to inherit from parent class in C:
*
*             #include "ParentClass.h"
*             typedef struct CHILDCLASS_STRUCT{
*               PARENTCLASS_STRUCT parent;
*               SOMETYPE           memberofchild;
*               ...
*             } * ChildClass;
*
*             to use the interface of ParentClass, e.g:
*             
*             ChildClass child = ChildClass_Create();
*             PARENTCLASS_METHOD((ParentClass)child,...);
*          c. Main purpose of this class is to provide common interface for Indexed Buffer
*             of all type. All Buffer Objects have the same shape interfaces (in the virtual 
*             table) following the exact same order below:
*             
*             void        INDEXER_SET (Buffer buf,unsigned int index, ElementType element);
*             ElementType INDEXER_GET (Buffer buf,unsigned int index);
* 
*             Different ElementTypes lead to different function signatures, however, due to
*             the exact same order, we know which one is the "set" indexer of all function.
*          d. children class should implement indexer as described below:
*              1) when index == 0, the value of the front element will be set or get.
*              2) when index == 1, the value of the second-front element. and so on.
*              3) when index == count - 1, the value of the back element.
*              4) there is no need to protect from the wrong index, this will make the indexer
*                 a common indexer. The correctness or the index is the responsibility of 
*                 the user.
*          e. If you want to add a Buffer Class of new ElementType, you need to implement
*             some methods to guide compiler to correct function signatures, just like 
*                    
*        void BufferUINT8Indexed_set(BufferUINT8Indexed buf,unsigned int index,uint8_t element);
*        uint8_t BufferUINT8Indexed_get(BufferUINT8Indexed buf,unsigned int index);
*
*             do. You can use Implementations of BufferUINT8Indexed Interface as a template
*             to create yours.
*          f. If you want to write an implementation for BufferUINT8Indexed Class, for 
*             example. the main work you should do is to inherit from the BufferIndexed Class
*             , implement the CONTAINER_INTERFACE ,BUFFER_INTERFACE and BUFFERINDEXED_INTERFACE.
*             And when creating the instance, assign the virtual table.
*             Then, when user call the interface, the corresponding interface will be called,
*             there is no need for NULL check in your interface implementation.
*          g. To reduce redundancy, it's recommended to adapt from the exist BufferIndexed Class,
*             whose element type take the same space as your new type, rather than create 
*             interfaces for new type. e.g,BufferChar can be adapted from BufferUINT8.
*          h. developer should implement the whole vtable, none of the interfaces in the
*             vtable can be left NULL. There will be no NULL check for vtable.
*******************************************************************************************
*/

#include "BufferIndexed.h"

typedef void (* BUFFERUINT8INDEXEDINTERFACE_SET)
  (BufferUINT8Indexed buf,unsigned int index,uint8_t element);
typedef uint8_t (* BUFFERUINT8INDEXEDINTERFACE_GET)
  (BufferUINT8Indexed buf,unsigned int index);
typedef void (* BUFFERUINT16INDEXEDINTERFACE_SET)
  (BufferUINT16Indexed buf,unsigned int index,uint16_t element);
typedef uint16_t (* BUFFERUINT16INDEXEDINTERFACE_GET)
  (BufferUINT16Indexed buf,unsigned int index);
typedef void (* BUFFERUINT32INDEXEDINTERFACE_SET)
  (BufferUINT32Indexed buf,unsigned int index,uint32_t element);
typedef uint32_t (* BUFFERUINT32INDEXEDINTERFACE_GET)
  (BufferUINT32Indexed buf,unsigned int index);

typedef struct BUFFERINDEXED_INTERFACE {
  BUFFERINTERFACE_POINTER set;
  BUFFERINTERFACE_POINTER get;
}BUFFERINDEXED_INTERFACE;

typedef BUFFERINDEXED_INTERFACE const * BUFFERINDEXED_INTERFACE_TABLE;

// compatible to all BUFFERXXX_STRUCT,due to the size of
// all BUFFERXXXXINTERFACE_TABLE are the same(one pointer).
typedef struct BUFFERINDEXED_STRUCT{
  BUFFER_STRUCT parent;
  BUFFERINDEXED_INTERFACE_TABLE vtable;
}BUFFERINDEXED_STRUCT;

// all private methods don't has NULL check.

#define _BufferIndexed_mVtable(buf)   (((BufferIndexed)(buf))->vtable)
#define _BufferIndexed_fSet(buf)      (_BufferIndexed_mVtable(buf)->set)
#define _BufferIndexed_fGet(buf)      (_BufferIndexed_mVtable(buf)->get)

void _BufferUINT8Indexed_set (BufferUINT8Indexed buf,unsigned int index,uint8_t element);
uint8_t _BufferUINT8Indexed_get(BufferUINT8Indexed buf,unsigned int index);
void _BufferUINT16Indexed_set (BufferUINT16Indexed buf,unsigned int index,uint16_t element);
uint16_t _BufferUINT16Indexed_get(BufferUINT16Indexed buf,unsigned int index);
void _BufferUINT32Indexed_set (BufferUINT32Indexed buf,unsigned int index,uint32_t element);
uint32_t _BufferUINT32Indexed_get(BufferUINT32Indexed buf,unsigned int index);

// initialize a BufferIndexed instance,you should implement all the interface, 
// except for Destroy(internal, no NULL check)
// void _BufferIndexed_Init(BufferIndexed buf,OBJECTINTERFACE_VOID fDestroy,
//  CONTAINER_INTERFACE_TABLE c_vtable,BUFFER_INTERFACE_TABLE vtable,
//  BUFFERINDEXED_INTERFACE_TABLE i_vtable);
#define _BufferIndexed_Init(buf, fDestroy, c_vtable, vtable, i_vtable)  \
   {_Buffer_Init((Buffer)buf, fDestroy, c_vtable, vtable);\
  _BufferIndexed_mVtable(buf) = i_vtable;}

BufferIndexed.c

/*
*******************************************************************************************
*
*                        Interface Implementation for All Indexed Buffer
*
* File : BufferIndexed.c
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): 
*******************************************************************************************
*/
#include "BufferIndexed.h"

/*void _BufferIndexed_Init(BufferIndexed buf,OBJECTINTERFACE_VOID fDestroy,
        CONTAINER_INTERFACE_TABLE c_vtable,BUFFER_INTERFACE_TABLE vtable,
        BUFFERINDEXED_INTERFACE_TABLE i_vtable){
  _Buffer_Init((Buffer)buf, fDestroy, c_vtable, vtable);
  _BufferIndexed_mVtable(buf) = i_vtable;
} // */

void BufferUINT8Indexed_set (BufferUINT8Indexed buf,unsigned int index,uint8_t element){
  if(buf)
    _BufferUINT8Indexed_set(buf,index,element);
}
uint8_t BufferUINT8Indexed_get(BufferUINT8Indexed buf,unsigned int index){
  if(buf)
    return _BufferUINT8Indexed_get(buf,index);
  return BUFFER_WHENERR_ELEMENTRETURN;
}
void BufferUINT16Indexed_set(BufferUINT16Indexed buf,unsigned int index,uint16_t element){
  if(buf)
    _BufferUINT16Indexed_set(buf,index,element);
}
uint16_t BufferUINT16Indexed_get(BufferUINT16Indexed buf,unsigned int index){
  if(buf)
    return _BufferUINT16Indexed_get(buf,index);
  return BUFFER_WHENERR_ELEMENTRETURN;
}
void BufferUINT32Indexed_set(BufferUINT32Indexed buf,unsigned int index,uint32_t element){
  if(buf)
    _BufferUINT32Indexed_set(buf,index,element);
}
uint32_t BufferUINT32Indexed_get(BufferUINT32Indexed buf,unsigned int index){
  if(buf)
    return _BufferUINT32Indexed_get(buf,index);
  return BUFFER_WHENERR_ELEMENTRETURN;
}


void _BufferUINT8Indexed_set (BufferUINT8Indexed buf,unsigned int index,uint8_t element){
  ((BUFFERUINT8INDEXEDINTERFACE_SET)_BufferIndexed_fSet(buf))(buf,index,element);
}
uint8_t _BufferUINT8Indexed_get(BufferUINT8Indexed buf,unsigned int index){
  return ((BUFFERUINT8INDEXEDINTERFACE_GET)_BufferIndexed_fGet(buf))(buf,index);
}
void _BufferUINT16Indexed_set (BufferUINT16Indexed buf,unsigned int index,uint16_t element){
  ((BUFFERUINT16INDEXEDINTERFACE_SET)_BufferIndexed_fSet(buf))(buf,index,element);
}
uint16_t _BufferUINT16Indexed_get(BufferUINT16Indexed buf,unsigned int index){
  return ((BUFFERUINT16INDEXEDINTERFACE_GET)_BufferIndexed_fGet(buf))(buf,index);
}
void _BufferUINT32Indexed_set (BufferUINT32Indexed buf,unsigned int index,uint32_t element){
  ((BUFFERUINT32INDEXEDINTERFACE_SET)_BufferIndexed_fSet(buf))(buf,index,element);
}
uint32_t _BufferUINT32Indexed_get(BufferUINT32Indexed buf,unsigned int index){
  return ((BUFFERUINT32INDEXEDINTERFACE_GET)_BufferIndexed_fGet(buf))(buf,index);
}

BufferArrayShare

BufferArrayShare.h

/*
*******************************************************************************************
*
*                       Share Parent Class for All Indexed Array Buffer
*
* File : BufferArrayShare.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. this class include the protected members and the corresponding methods that
*             share for Buffers that implemented with numerically indexed array.
*******************************************************************************************
*/
#ifndef _BUFFERARRAYSHARE_H
#define _BUFFERARRAYSHARE_H

#include "BufferIndexed.h"

typedef struct BUFFERARRAYSHARE_STRUCT
  * BufferArrayShare;

#include "BufferArraySharePrivate.h"
#endif

BufferArraySharePrivate.h

/*
*******************************************************************************************
*
*                        Share Parent Class for All Indexed Array Buffer
*
* File : BufferArraySharePrivate.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. this file is only for the developer, user shouldn't use any in this file.
*          b. to inherit from parent class in C:
*
*             #include "ParentClass.h"
*             typedef struct CHILDCLASS_STRUCT{
*               PARENTCLASS_STRUCT parent;
*               SOMETYPE           memberofchild;
*               ...
*             } * ChildClass;
*
*             to use the interface of ParentClass, e.g:
*             
*             ChildClass child = ChildClass_Create();
*             PARENTCLASS_METHOD((ParentClass)child,...);
*
*  !!!!!  the "index" below refers to the internal(actual) index, not the index for indexer !!!!!
*
*          a. I assume most developer would like to use an circle-indexed array or something
*             similar to implement the Buffer. So here provide the share members and methods.
*             the use of 'capacity' and 'count' is obvious. 'front' and 'back' are the internal
*             index for front-element and back-element respectively. 'front'
*             refers to the actual position front-element at.   
*          b. Index here is 0-based and up to   buffer's capacity - 1  . 
*             _BufferArrayShare_Inc/decXXXIndex will treat front or back index as circle.
*          c. compatible to all BUFFERUINTXXX_STRUCT,due to the size of all INTERFACE_TABLE
*             are the same(one pointer).
*          d. this class assumes add element at front will cause frontIndex to decrease,
*             and add element at back will cause backIndex to increase.
*             so _BufferIndexed_Init will init frontIndex bigger than backIndex by 1
*******************************************************************************************
*/

#include "BufferArrayShare.h"

typedef struct BUFFERARRAYSHARE_STRUCT{
  BUFFERINDEXED_STRUCT parent;  // compatible to all BUFFERXXX_STRUCT,due to the size of
                                // all BUFFERXXXXINTERFACE_TABLE are the same(one pointer).
  unsigned int capacity;        // the capacity
  unsigned int count;           // count of elements
  unsigned int front;           // index of the front element in the array
  unsigned int back;            // index of the back  element in the array
}BUFFERARRAYSHARE_STRUCT;

// common container interface for all 
extern const CONTAINER_INTERFACE _ContainerInterface_ArrayShare;
// all private methods don't has NULL check.
#define _BufferArrayShare_mCapacity(buf)    (((BufferArrayShare)(buf))->capacity)
#define _BufferArrayShare_mCount(buf)       (((BufferArrayShare)(buf))->count)
#define _BufferArrayShare_mFront(buf)       (((BufferArrayShare)(buf))->front)
#define _BufferArrayShare_mBack(buf)        (((BufferArrayShare)(buf))->back)

// initialize a BufferIndexed instance, count is assumed to be initialized to 0
// and frontIndex will bigger than backIndex by 1  (internal, no NULL check)
void _BufferArrayShare_Init(BufferArrayShare buf,OBJECTINTERFACE_VOID fDestroy,
  CONTAINER_INTERFACE_TABLE c_vtable, BUFFER_INTERFACE_TABLE vtable,
  BUFFERINDEXED_INTERFACE_TABLE indexer, unsigned int capacity);
// operation on index front
void _BufferArrayShare_IncFrontIndex(BufferArrayShare buf);
// operation on index front
void _BufferArrayShare_DecFrontIndex(BufferArrayShare buf);
// operation on index back
void _BufferArrayShare_IncBackIndex(BufferArrayShare buf);
// operation on index back
void _BufferArrayShare_DecBackIndex(BufferArrayShare buf);


// Common cleanup Interface implementation for all Indexed Array Buffer
// just care about front, back and count members. Used by the implementations below.
void _BufferArrayShare_Cleanup(BufferArrayShare buf);

// Common Interface implementations for all Buffers which use indexed array as internal storage.
// In these implementations:
//    When buffer is empty, front, back, frontOut and back will return BUFFER_WHENERR_ELEMENTRETURN.
//    When buffer is full, frontIn and backOut will just ignore the call.
// if you use these interface, just make sure you implement the indexer correctly, then Buffer should
// work properly.
extern const BUFFER_INTERFACE _BufferInterface_ArrayUint8;
extern const BUFFER_INTERFACE _BufferInterface_ArrayUint16;
extern const BUFFER_INTERFACE _BufferInterface_ArrayUint32;

// calculate the internal(actual) index by relative index
// very useful for implementations which use an array for storage.
unsigned int _BufferArrayShare_calInternalIndex(BufferArrayShare buf,unsigned int relativeIndex);

BufferArrayShare.c

/*
*******************************************************************************************
*
*                     Common Implementation for All Indexed Array Buffer
*
* File : BufferArrayShare.c
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): 
*******************************************************************************************
*/

#include "BufferArrayShare.h"


void _BufferArrayShare_Init(BufferArrayShare buf,OBJECTINTERFACE_VOID fDestroy,
       CONTAINER_INTERFACE_TABLE c_vtable, BUFFER_INTERFACE_TABLE vtable,
       BUFFERINDEXED_INTERFACE_TABLE indexer, unsigned int capacity){
  _BufferIndexed_Init((BufferIndexed)buf, fDestroy, c_vtable,vtable,indexer);
  _BufferArrayShare_Cleanup(buf);
  _BufferArrayShare_mCapacity(buf) = capacity;
}

void _BufferArrayShare_IncFrontIndex(BufferArrayShare buf){
  if(++_BufferArrayShare_mFront(buf) >=  _BufferArrayShare_mCapacity(buf))
    _BufferArrayShare_mFront(buf) = 0;
}

void _BufferArrayShare_DecFrontIndex(BufferArrayShare buf){
  if(_BufferArrayShare_mFront(buf)-- == 0)
    _BufferArrayShare_mFront(buf) = _BufferArrayShare_mCapacity(buf) - 1;
}

void _BufferArrayShare_IncBackIndex(BufferArrayShare buf){
  if(++_BufferArrayShare_mBack(buf) >= _BufferArrayShare_mCapacity(buf))
    _BufferArrayShare_mBack(buf) = 0;
}

void _BufferArrayShare_DecBackIndex(BufferArrayShare buf){
  if(_BufferArrayShare_mBack(buf)-- == 0)
    _BufferArrayShare_mBack(buf) = _BufferArrayShare_mCapacity(buf) - 1;
}

void _BufferArrayShare_Cleanup(BufferArrayShare buf){
  _BufferArrayShare_mFront(buf) = 1;
  _BufferArrayShare_mBack(buf) = 0;
  _BufferArrayShare_mCount(buf) = 0;
}

// share container-interface for indexed array
static unsigned int _getCapacity(Container ct){
  return _BufferArrayShare_mCapacity(ct);
}
static unsigned int _getCount(Container ct){
  return _BufferArrayShare_mCount(ct);
}
const CONTAINER_INTERFACE _ContainerInterface_ArrayShare = {_getCapacity,_getCount};



unsigned int _BufferArrayShare_calInternalIndex(BufferArrayShare buf,unsigned int relativeIndex){
  // here has a bug, if the capacity is big enough, _BufferArrayShare_mFront(buf) + relativeIndex
  // may exceed the UINT_MAX, however, I don't think you will need a buffer so big.
  unsigned int internalIndex;
  internalIndex = _BufferArrayShare_mFront(buf) + relativeIndex;
  if(internalIndex >= _BufferArrayShare_mCapacity(buf))
    internalIndex -= _BufferArrayShare_mCapacity(buf);
  return internalIndex;
}


#define incFrontIndex(buf)       _BufferArrayShare_IncFrontIndex((BufferArrayShare)buf)
#define decFrontIndex(buf)       _BufferArrayShare_DecFrontIndex((BufferArrayShare)buf)
#define incBackIndex(buf)        _BufferArrayShare_IncBackIndex((BufferArrayShare)buf)
#define decBackIndex(buf)        _BufferArrayShare_DecBackIndex((BufferArrayShare )buf)
static uint8_t _Front_uint8(BufferUINT8 buf);
static uint8_t _Back_uint8(BufferUINT8 buf);
static void _FrontIn_uint8(BufferUINT8 buf,uint8_t element);
static void _BackIn_uint8(BufferUINT8 buf,uint8_t element);
static uint8_t _FrontOut_uint8(BufferUINT8 buf);
static uint8_t _BackOut_uint8(BufferUINT8 buf);

const BUFFER_INTERFACE _BufferInterface_ArrayUint8 = {
  (BUFFERINTERFACE_POINTER)_Front_uint8,
  (BUFFERINTERFACE_POINTER)_Back_uint8,
  (BUFFERINTERFACE_POINTER)_FrontIn_uint8,
  (BUFFERINTERFACE_POINTER)_BackIn_uint8,
  (BUFFERINTERFACE_POINTER)_FrontOut_uint8,
  (BUFFERINTERFACE_POINTER)_BackOut_uint8,
  (BUFFERINTERFACE_VOID)_BufferArrayShare_Cleanup
};

static uint16_t _Front_uint16(BufferUINT16 buf);
static uint16_t _Back_uint16(BufferUINT16 buf);
static void _FrontIn_uint16(BufferUINT16 buf,uint16_t element);
static void _BackIn_uint16(BufferUINT16 buf,uint16_t element);
static uint16_t _FrontOut_uint16(BufferUINT16 buf);
static uint16_t _BackOut_uint16(BufferUINT16 buf);

const BUFFER_INTERFACE _BufferInterface_ArrayUint16 = {
  (BUFFERINTERFACE_POINTER)_Front_uint16,
  (BUFFERINTERFACE_POINTER)_Back_uint16,
  (BUFFERINTERFACE_POINTER)_FrontIn_uint16,
  (BUFFERINTERFACE_POINTER)_BackIn_uint16,
  (BUFFERINTERFACE_POINTER)_FrontOut_uint16,
  (BUFFERINTERFACE_POINTER)_BackOut_uint16,
  (BUFFERINTERFACE_VOID)_BufferArrayShare_Cleanup
};

static uint32_t _Front_uint32(BufferUINT32 buf);
static uint32_t _Back_uint32(BufferUINT32 buf);
static void _FrontIn_uint32(BufferUINT32 buf,uint32_t element);
static void _BackIn_uint32(BufferUINT32 buf,uint32_t element);
static uint32_t _FrontOut_uint32(BufferUINT32 buf);
static uint32_t _BackOut_uint32(BufferUINT32 buf);

const BUFFER_INTERFACE _BufferInterface_ArrayUint32 = {
  (BUFFERINTERFACE_POINTER)_Front_uint32,
  (BUFFERINTERFACE_POINTER)_Back_uint32,
  (BUFFERINTERFACE_POINTER)_FrontIn_uint32,
  (BUFFERINTERFACE_POINTER)_BackIn_uint32,
  (BUFFERINTERFACE_POINTER)_FrontOut_uint32,
  (BUFFERINTERFACE_POINTER)_BackOut_uint32,
  (BUFFERINTERFACE_VOID)_BufferArrayShare_Cleanup
};

static uint8_t _Front_uint8(BufferUINT8 buf){
  unsigned int cnt = _BufferArrayShare_mCount(buf);
  if(cnt == 0)
    return BUFFER_WHENERR_ELEMENTRETURN;
  return _BufferUINT8Indexed_get((BufferUINT8Indexed)buf,0);
}

static uint8_t _Back_uint8(BufferUINT8 buf){
  unsigned int cnt = _BufferArrayShare_mCount(buf);
  if(cnt == 0)
    return BUFFER_WHENERR_ELEMENTRETURN;
  return _BufferUINT8Indexed_get((BufferUINT8Indexed)buf,cnt - 1);
}

static void _FrontIn_uint8(BufferUINT8 buf,uint8_t element){
  if(_Buffer_isFull(buf))
    return;
  decFrontIndex(buf);
  ++_BufferArrayShare_mCount(buf);
  _BufferUINT8Indexed_set((BufferUINT8Indexed)buf,0,element);
}

static void _BackIn_uint8(BufferUINT8 buf,uint8_t element){
  unsigned int cnt = _BufferArrayShare_mCount(buf);
  if(_Buffer_isFull(buf))
    return;
  incBackIndex(buf);
  ++_BufferArrayShare_mCount(buf);
  _BufferUINT8Indexed_set((BufferUINT8Indexed)buf,cnt,element);
}

static uint8_t _FrontOut_uint8(BufferUINT8 buf){
  uint8_t rst;
  unsigned int cnt = _BufferArrayShare_mCount(buf);
  if(cnt == 0)
    return BUFFER_WHENERR_ELEMENTRETURN;
  rst = _BufferUINT8Indexed_get((BufferUINT8Indexed)buf,0);
  incFrontIndex(buf);
  --_BufferArrayShare_mCount(buf);
  return rst;
}

static uint8_t _BackOut_uint8(BufferUINT8 buf){
  uint8_t rst;
  unsigned int cnt = _BufferArrayShare_mCount(buf);
  if(cnt == 0)
    return BUFFER_WHENERR_ELEMENTRETURN;
  rst = _BufferUINT8Indexed_get((BufferUINT8Indexed)buf,cnt - 1);
  decBackIndex(buf);
  --_BufferArrayShare_mCount(buf);
  return rst;
}

static uint16_t _Front_uint16(BufferUINT16 buf){
  unsigned int cnt = _BufferArrayShare_mCount(buf);
  if(cnt == 0)
    return BUFFER_WHENERR_ELEMENTRETURN;
  return _BufferUINT16Indexed_get((BufferUINT16Indexed)buf,0);
}

static uint16_t _Back_uint16(BufferUINT16 buf){
  unsigned int cnt = _BufferArrayShare_mCount(buf);
  if(cnt == 0)
    return BUFFER_WHENERR_ELEMENTRETURN;
  return _BufferUINT16Indexed_get((BufferUINT16Indexed)buf,cnt - 1);
}

static void _FrontIn_uint16(BufferUINT16 buf,uint16_t element){
  if(_Buffer_isFull(buf))
    return;
  decFrontIndex(buf);
  ++_BufferArrayShare_mCount(buf);
  _BufferUINT16Indexed_set((BufferUINT16Indexed)buf,0,element);
}

static void _BackIn_uint16(BufferUINT16 buf,uint16_t element){
  unsigned int cnt = _BufferArrayShare_mCount(buf);
  if(_Buffer_isFull(buf))
    return;
  incBackIndex(buf);
  ++_BufferArrayShare_mCount(buf);
  _BufferUINT16Indexed_set((BufferUINT16Indexed)buf,cnt,element);
}

static uint16_t _FrontOut_uint16(BufferUINT16 buf){
  uint16_t rst;
  unsigned int cnt = _BufferArrayShare_mCount(buf);
  if(cnt == 0)
    return BUFFER_WHENERR_ELEMENTRETURN;
  rst = _BufferUINT16Indexed_get((BufferUINT16Indexed)buf,0);
  incFrontIndex(buf);
  --_BufferArrayShare_mCount(buf);
  return rst;
}

static uint16_t _BackOut_uint16(BufferUINT16 buf){
  uint16_t rst;
  unsigned int cnt = _BufferArrayShare_mCount(buf);
  if(cnt == 0)
    return BUFFER_WHENERR_ELEMENTRETURN;
  rst = _BufferUINT16Indexed_get((BufferUINT16Indexed)buf,cnt - 1);
  decBackIndex(buf);
  --_BufferArrayShare_mCount(buf);
  return rst;
}


static uint32_t _Front_uint32(BufferUINT32 buf){
  unsigned int cnt = _BufferArrayShare_mCount(buf);
  if(cnt == 0)
    return BUFFER_WHENERR_ELEMENTRETURN;
  return _BufferUINT32Indexed_get((BufferUINT32Indexed)buf,0);
}

static uint32_t _Back_uint32(BufferUINT32 buf){
  unsigned int cnt = _BufferArrayShare_mCount(buf);
  if(cnt == 0)
    return BUFFER_WHENERR_ELEMENTRETURN;
  return _BufferUINT32Indexed_get((BufferUINT32Indexed)buf,cnt - 1);
}

static void _FrontIn_uint32(BufferUINT32 buf,uint32_t element){
  if(_Buffer_isFull(buf))
    return;
  decFrontIndex(buf);
  ++_BufferArrayShare_mCount(buf);
  _BufferUINT32Indexed_set((BufferUINT32Indexed)buf,0,element);
}

static void _BackIn_uint32(BufferUINT32 buf,uint32_t element){
  unsigned int cnt = _BufferArrayShare_mCount(buf);
  if(_Buffer_isFull(buf))
    return;
  incBackIndex(buf);
  ++_BufferArrayShare_mCount(buf);
  _BufferUINT32Indexed_set((BufferUINT32Indexed)buf,cnt,element);
}

static uint32_t _FrontOut_uint32(BufferUINT32 buf){
  uint32_t rst;
  unsigned int cnt = _BufferArrayShare_mCount(buf);
  if(cnt == 0)
    return BUFFER_WHENERR_ELEMENTRETURN;
  rst = _BufferUINT32Indexed_get((BufferUINT32Indexed)buf,0);
  incFrontIndex(buf);
  --_BufferArrayShare_mCount(buf);
  return rst;
}

static uint32_t _BackOut_uint32(BufferUINT32 buf){
  uint32_t rst;
  unsigned int cnt = _BufferArrayShare_mCount(buf);
  if(cnt == 0)
    return BUFFER_WHENERR_ELEMENTRETURN;
  rst = _BufferUINT32Indexed_get((BufferUINT32Indexed)buf,cnt - 1);
  decBackIndex(buf);
  --_BufferArrayShare_mCount(buf);
  return rst;
}

BufferArray

BufferArray.h

/*
*******************************************************************************************
*
*                  Parent Class for All Indexed Array Buffer with normal pointer
*
* File : BufferArray.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. This class provide the pointer members for Buffers which use a (near) numerically 
*             indexed array internal. And the indexer for UINT8, UINT16 and UINT32 Buffer.
*******************************************************************************************
*/

#ifndef _BUFFERARRAY_H
#define _BUFFERARRAY_H

#include "BufferArrayShare.h"

typedef struct BUFFERARRAY_STRUCT 
  * BufferArray, 
  * BufferUINT8Array,
  * BufferUINT16Array,
  * BufferUINT32Array;

#include "BufferArrayPrivate.h"

#endif

BufferArrayPrivate.h

/*
*******************************************************************************************
*
*                    Parent Class for All Indexed Array Buffer with normal pointer
*
* File : BufferArrayPrivate.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. This class provide the pointer members for Buffers which use a (near) numerically 
*             indexed array internal. And the indexer for UINT8, UINT16 and UINT32 Buffer.
*          b. Generally, to implement an indexed array buffer, developer just need to implement
*             a Create method, which allocates space for BUFFERARRAY_STRUCT and use the Init
*             method in this file to initialize it, plus the corresponding destroy method;
*             then everything will go right.
*******************************************************************************************
*/
#include "BufferArray.h"

typedef struct BUFFERARRAY_STRUCT{
  BUFFERARRAYSHARE_STRUCT parent;
  union{
    uint8_t  * uint8;
    uint16_t * uint16;
    uint32_t * uint32;
    void     * ptr;
  }ptr;
} BUFFERARRAY_STRUCT;

#define _BufferArray_ptrUint8(buf)    (((BufferUINT8Array )buf)->ptr.uint8)
#define _BufferArray_ptrUint16(buf)   (((BufferUINT16Array)buf)->ptr.uint16)
#define _BufferArray_ptrUint32(buf)   (((BufferUINT32Array)buf)->ptr.uint32)
#define _BufferArray_ptr(buf)         (((BufferArray      )buf)->ptr.ptr)

// common indexer interface for normal array, use the indexer to access internal element.
// so you should implement the indexer correctly as description.
extern const BUFFERINDEXED_INTERFACE _BufferIndexedInterface_ArrayUint8;
extern const BUFFERINDEXED_INTERFACE _BufferIndexedInterface_ArrayUint16;
extern const BUFFERINDEXED_INTERFACE _BufferIndexedInterface_ArrayUint32;

void _BufferArray_Init(BufferArray buf,void *ptr,unsigned int capacity,
                       OBJECTINTERFACE_VOID fDestroy, BUFFER_INTERFACE_TABLE vtable,
                       BUFFERINDEXED_INTERFACE_TABLE i_vtable);
#define  _BufferUINT8Array_Init(buf,ptr,capacity,fDestroy)   \
  _BufferArray_Init(buf,ptr,capacity,fDestroy,&_BufferInterface_ArrayUint8,\
  &_BufferIndexedInterface_ArrayUint8);
#define  _BufferUINT16Array_Init(buf,ptr,capacity,fDestroy)   \
  _BufferArray_Init(buf,ptr,capacity,fDestroy,&_BufferInterface_ArrayUint16,\
  &_BufferIndexedInterface_ArrayUint16);
#define  _BufferUINT32Array_Init(buf,ptr,capacity,fDestroy)   \
  _BufferArray_Init(buf,ptr,capacity,fDestroy,&_BufferInterface_ArrayUint32,\
  &_BufferIndexedInterface_ArrayUint32);

BufferArray.c

/*
*******************************************************************************************
*
*                  Parent Class for All Indexed Array Buffer with normal pointer
*
* File : BufferArray.c
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): 
*******************************************************************************************
*/
#include "BufferArray.h"

void _BufferArray_Init(BufferArray buf,void *ptr,unsigned int capacity,
  OBJECTINTERFACE_VOID fDestroy, BUFFER_INTERFACE_TABLE vtable,BUFFERINDEXED_INTERFACE_TABLE i_vtable){
  _BufferArrayShare_Init((BufferArrayShare)buf,fDestroy,
    &_ContainerInterface_ArrayShare,vtable,i_vtable,capacity);
  _BufferArray_ptr(buf) = ptr;
}

uint8_t *_BufferIndexer_ArrayUint8(BufferIndexed buf,unsigned int index){
  return _BufferArray_ptrUint8(buf) + _BufferArrayShare_calInternalIndex((BufferArrayShare)buf,index);
}

uint16_t *_BufferIndexer_ArrayUint16(BufferIndexed buf,unsigned int index){
  return _BufferArray_ptrUint16(buf) + _BufferArrayShare_calInternalIndex((BufferArrayShare)buf,index);
}

uint32_t *_BufferIndexer_ArrayUint32(BufferIndexed buf,unsigned int index){
  return _BufferArray_ptrUint32(buf) + _BufferArrayShare_calInternalIndex((BufferArrayShare)buf,index);
}

static void _Uint8Setter(BufferUINT8Indexed buf,unsigned int index,uint8_t element){
  * _BufferIndexer_ArrayUint8(buf,index) = element;
}
static uint8_t _Uint8Getter(BufferUINT8Indexed buf,unsigned int index){
  return * _BufferIndexer_ArrayUint8(buf,index);
}
static void _Uint16Setter(BufferUINT16Indexed buf,unsigned int index,uint16_t element){
  * _BufferIndexer_ArrayUint16(buf,index) = element;
}
static uint16_t _Uint16Getter(BufferUINT16Indexed buf,unsigned int index){
  return * _BufferIndexer_ArrayUint16(buf,index);
}
static void _Uint32Setter(BufferUINT32Indexed buf,unsigned int index,uint32_t element){
  * _BufferIndexer_ArrayUint32(buf,index) = element;
}
static uint32_t _Uint32Getter(BufferUINT32Indexed buf,unsigned int index){
  return * _BufferIndexer_ArrayUint32(buf,index);
}
const BUFFERINDEXED_INTERFACE _BufferIndexedInterface_ArrayUint8 = {
  (BUFFERINTERFACE_POINTER)_Uint8Setter,
  (BUFFERINTERFACE_POINTER)_Uint8Getter
};
const BUFFERINDEXED_INTERFACE _BufferIndexedInterface_ArrayUint16 = {
  (BUFFERINTERFACE_POINTER)_Uint16Setter,
  (BUFFERINTERFACE_POINTER)_Uint16Getter
};
const BUFFERINDEXED_INTERFACE _BufferIndexedInterface_ArrayUint32 = {
  (BUFFERINTERFACE_POINTER)_Uint32Setter,
  (BUFFERINTERFACE_POINTER)_Uint32Getter
};

BufferExternalArray

BufferExternalArray.h

/*
*******************************************************************************************
*
*                             An Implementation for BufferArray
*
* File : BufferExternalArray.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. An implementation for BufferArray, which manage the array passed by user.
*          b. Inheritance tree: Container -> BufferTYPE -> BufferTYPEIndexed -> 
*             BufferTYPEArrayShare -> BufferTYPEArray
*                 where TYPE can be UINT8, UINT16, UINT32 ......
*             See the header file of each class to figure out which it can do.
*******************************************************************************************
*/

#ifndef _BUFFER_EXTERNAL_ARRAY_H
#define _BUFFER_EXTERNAL_ARRAY_H

/*
*******************************************************************************************
*                                    INCLUDES
*******************************************************************************************
*/

#include "BufferArray.h"

/*
*******************************************************************************************
*                                     FUNCTIONS
*******************************************************************************************
*/


// description: Create an instance of BufferArray
// parameters : arr        the array to be managed by the BufferArray
//              capacity   the size of the array
// return     : the instance created.
//              NULL       if anything wrong.
// note       : in the lifetime of the instance, you should never touch the array, just
//              think it as the private property of the instance
BufferUINT8Array  BufferUINT8ExternalArray_Create (uint8_t  * arr, unsigned int capacity);
BufferUINT16Array BufferUINT16ExternalArray_Create(uint16_t * arr, unsigned int capacity);
BufferUINT32Array BufferUINT32ExternalArray_Create(uint32_t * arr, unsigned int capacity);

#endif

BufferExternalArray.c

/*
*******************************************************************************************
*
*                             An Implementation for BufferArray
*
* File : BufferExternalArray.c
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. An implementation for BufferArray, which use the array passed by user.
*          b. Inheritance tree: Container -> BufferTYPE -> BufferTYPEIndexed -> 
*             BufferTYPEArrayShare -> BufferTYPEArray
*                 where TYPE can be UINT8, UINT16, UINT32 ......
*             See the header file of each class to figure out which it can do.
*******************************************************************************************
*/

#include <stdlib.h>
#include "BufferExternalArray.h"

BufferUINT8Array  BufferUINT8ExternalArray_Create (uint8_t  * arr, unsigned int capacity){
  BufferUINT8Array buf = (BufferUINT8Array)malloc(sizeof(BUFFERARRAY_STRUCT));
  if(buf)
    _BufferUINT8Array_Init(buf, arr,capacity,_Destroy_JustCallFree);
  return buf;
}
BufferUINT16Array  BufferUINT16ExternalArray_Create (uint16_t  * arr, unsigned int capacity){
  BufferUINT16Array buf = (BufferUINT16Array)malloc(sizeof(BUFFERARRAY_STRUCT));
  if(buf)
    _BufferUINT16Array_Init(buf, arr,capacity,_Destroy_JustCallFree);
  return buf;
}
BufferUINT32Array  BufferUINT32ExternalArray_Create (uint32_t  * arr, unsigned int capacity){
  BufferUINT32Array buf = (BufferUINT32Array)malloc(sizeof(BUFFERARRAY_STRUCT));
  if(buf)
    _BufferUINT32Array_Init(buf, arr,capacity,_Destroy_JustCallFree);
  return buf;
}

BufferMallocArray

BufferMallocArray.h

/*
*******************************************************************************************
*
*                             A Common Implementation for BufferArray
*
* File : BufferMallocArray.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. A common implementation for BufferArray, which use malloc to allocate space
*          b. Inheritance tree: Container -> BufferTYPE -> BufferTYPEIndexed -> 
*             BufferTYPEArrayShare -> BufferTYPEArray
*                 where TYPE can be UINT8, UINT16 or UINT32.
*             See the header file of each class to figure out which it can do.
*******************************************************************************************
*/

#ifndef _BUFFER_MALLOC_ARRAY_H
#define _BUFFER_MALLOC_ARRAY_H

/*
*******************************************************************************************
*                                    INCLUDES
*******************************************************************************************
*/

#include "BufferArray.h"

/*
*******************************************************************************************
*                                     FUNCTIONS
*******************************************************************************************
*/

BufferUINT8Array BufferUINT8MallocArray_Create(unsigned int capacity);
BufferUINT16Array BufferUINT16MallocArray_Create(unsigned int capacity);
BufferUINT32Array BufferUINT32MallocArray_Create(unsigned int capacity);

#endif

BufferMallocArray.c

/*
*******************************************************************************************
*
*                             A Common Implementation for BufferArray
*
* File : BufferMallocArray.c
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. A common implementation for BufferArray, which use malloc to allocate space
*          b. Inheritance tree: Container -> BufferTYPE -> BufferTYPEIndexed -> 
*             BufferTYPEArrayShare -> BufferTYPEArray
*                 where TYPE can be UINT8, UINT16 or UINT32.
*             See the header file of each class to figure out which it can do.
*******************************************************************************************
*/

#include <stdlib.h>
#include "BufferMallocArray.h"

#ifndef UINT_MAX
#define UINT_MAX    ((unsigned int)-1)
#endif

static void _Destroy(void * buf);
static BufferArray _BufferMallocArray_Create(unsigned int arrSize,unsigned int capacity,
  BUFFER_INTERFACE_TABLE vtable,BUFFERINDEXED_INTERFACE_TABLE indexer);

BufferUINT8Array BufferUINT8MallocArray_Create(unsigned int capacity){
  return (BufferUINT8Array)_BufferMallocArray_Create
    (capacity,capacity,&_BufferInterface_ArrayUint8,&_BufferIndexedInterface_ArrayUint8);
}

BufferUINT16Array BufferUINT16MallocArray_Create(unsigned int capacity){
  if(capacity > (UINT_MAX >> 1))
    return NULL;
  return (BufferUINT16Array)_BufferMallocArray_Create
    (capacity << 1,capacity,&_BufferInterface_ArrayUint16,&_BufferIndexedInterface_ArrayUint16);
}

BufferUINT32Array BufferUINT32MallocArray_Create(unsigned int capacity){
  if(capacity > (UINT_MAX >> 2))
    return NULL;
  return (BufferUINT32Array)_BufferMallocArray_Create
    (capacity << 2,capacity,&_BufferInterface_ArrayUint32,&_BufferIndexedInterface_ArrayUint32);
}

static BufferArray _BufferMallocArray_Create(unsigned int arrSize,unsigned int capacity,
  BUFFER_INTERFACE_TABLE vtable,BUFFERINDEXED_INTERFACE_TABLE indexer){
    uint8_t * ptr = NULL;
    BufferArray buf;
    if(capacity != 0 && (ptr = (uint8_t *)malloc(arrSize)) == NULL)
      return NULL;
    if((buf = (BufferArray)malloc(sizeof(BUFFERARRAY_STRUCT))) == NULL){
      if(ptr) 
        free(ptr);
      return NULL;
    }
    _BufferArray_Init(buf,ptr,capacity, _Destroy,vtable,indexer);
    return buf;
}

static void _Destroy(void * buf){
  if(buf == NULL)
    return;
  if(_BufferArray_ptr(buf))
    free(_BufferArray_ptr(buf));
  free(buf);
}

BufferArrayR

BufferArrayR.h

注意要使用这个模块得宏定义CODEWARRIOR,否则效果和BufferArray一样

/*
*******************************************************************************************
*
*                  Parent Class for All Indexed Array Buffer with rpage pointer
*
* File : BufferArrayR.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. This class provide the pointer members for Buffers which use a RPAGE numerically 
*             indexed array internal. And the indexer for UINT8, UINT16 and UINT32 Buffer.
*          b. To use this module, #define CODEWARRIOR marco (maybe in your complier option)
*             or it will act same as the BufferArray.
*******************************************************************************************
*/

#ifndef _BUFFERARRAYR_H
#define _BUFFERARRAYR_H

#include "BufferArrayShare.h"

typedef struct BUFFERARRAYR_STRUCT 
  * BufferArrayR, 
  * BufferUINT8ArrayR,
  * BufferUINT16ArrayR,
  * BufferUINT32ArrayR;

#include "BufferArrayRPrivate.h"

#endif

BufferArrayRPrivate.h

/*
*******************************************************************************************
*
*                          Parent Class for All RPAGE Indexed Array Buffer
*
* File : BufferArrayRPrivate.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. This class provide the pointer members for Buffers which use a RPAGE numerically 
*             indexed array internal. And the indexer for UINT8, UINT16 and UINT32 Buffer.
*          b. Generally, to implement an indexed array buffer, developer just need to implement
*             a Create method, which allocates space for BUFFERARRAYR_STRUCT and use the Init
*             method in this file to initialize it, plus the corresponding destroy method;
*             then everything will go right.
*******************************************************************************************
*/
#include "BufferArrayR.h"

#ifdef CODEWARRIOR
#define __RPTR __rptr
#else
#define __RPTR
#endif

typedef struct BUFFERARRAYR_STRUCT{
  BUFFERARRAYSHARE_STRUCT parent;
  union{
    uint8_t  * __RPTR uint8;
    uint16_t * __RPTR uint16;
    uint32_t * __RPTR uint32;
    void     * __RPTR ptr;
  }ptr;
} BUFFERARRAYR_STRUCT;

#define _BufferArrayR_ptrUint8(buf)    (((BufferUINT8ArrayR )buf)->ptr.uint8)
#define _BufferArrayR_ptrUint16(buf)   (((BufferUINT16ArrayR)buf)->ptr.uint16)
#define _BufferArrayR_ptrUint32(buf)   (((BufferUINT32ArrayR)buf)->ptr.uint32)
#define _BufferArrayR_ptr(buf)         (((BufferArrayR      )buf)->ptr.ptr)

// common indexer interface for rpaged array, use the indexer to access internal element.
// so you should implement the indexer correctly as description.
extern const BUFFERINDEXED_INTERFACE _BufferIndexedInterface_ArrayRUint8;
extern const BUFFERINDEXED_INTERFACE _BufferIndexedInterface_ArrayRUint16;
extern const BUFFERINDEXED_INTERFACE _BufferIndexedInterface_ArrayRUint32;

void _BufferArrayR_Init(BufferArrayR buf,void * __RPTR ptr,unsigned int capacity,
                       OBJECTINTERFACE_VOID fDestroy, BUFFER_INTERFACE_TABLE vtable,
                       BUFFERINDEXED_INTERFACE_TABLE i_vtable);
// void _BufferUINT8ArrayR_Init(BufferUINT8ArrayR buf,uint8_t * __rptr ptr,unsigned int capacity, OBJECTINTERFACE_VOID fDestroy);
#define  _BufferUINT8ArrayR_Init(buf,ptr,capacity,fDestroy)   \
  _BufferArrayR_Init(buf,ptr,capacity,fDestroy,&_BufferInterface_ArrayUint8,\
  &_BufferIndexedInterface_ArrayRUint8);
// void _BufferUINT16ArrayR_Init(BufferUINT16ArrayR buf,uint16_t * __rptr ptr,unsigned int capacity, OBJECTINTERFACE_VOID fDestroy);
#define  _BufferUINT16ArrayR_Init(buf,ptr,capacity,fDestroy)   \
  _BufferArrayR_Init(buf,ptr,capacity,fDestroy,&_BufferInterface_ArrayUint16,\
  &_BufferIndexedInterface_ArrayRUint16);
// void _BufferUINT32ArrayR_Init(BufferUINT32ArrayR buf,uint32_t * __rptr ptr,unsigned int capacity, OBJECTINTERFACE_VOID fDestroy);
#define  _BufferUINT32ArrayR_Init(buf,ptr,capacity,fDestroy)   \
  _BufferArrayR_Init(buf,ptr,capacity,fDestroy,&_BufferInterface_ArrayUint32,\
  &_BufferIndexedInterface_ArrayRUint32);

BufferArrayR.c

/*
*******************************************************************************************
*
*                  Parent Class for All Indexed Array Buffer with rpage pointer
*
* File : BufferArrayR.c
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): 
*******************************************************************************************
*/
#include "BufferArrayR.h"

void _BufferArrayR_Init(BufferArrayR buf,void *__RPTR ptr,unsigned int capacity, OBJECTINTERFACE_VOID fDestroy,
 BUFFER_INTERFACE_TABLE vtable,BUFFERINDEXED_INTERFACE_TABLE i_vtable){
  _BufferArrayShare_Init((BufferArrayShare)buf,fDestroy,
    &_ContainerInterface_ArrayShare,vtable,i_vtable,capacity);
  _BufferArrayR_ptr(buf) = ptr;
}

uint8_t * __RPTR _BufferIndexer_ArrayRUint8(BufferIndexed buf,unsigned int index){
  return _BufferArrayR_ptrUint8(buf) + _BufferArrayShare_calInternalIndex((BufferArrayShare)buf,index);
}

uint16_t * __RPTR _BufferIndexer_ArrayRUint16(BufferIndexed buf,unsigned int index){
  return _BufferArrayR_ptrUint16(buf) + _BufferArrayShare_calInternalIndex((BufferArrayShare)buf,index);
}

uint32_t * __RPTR _BufferIndexer_ArrayRUint32(BufferIndexed buf,unsigned int index){
  return _BufferArrayR_ptrUint32(buf) + _BufferArrayShare_calInternalIndex((BufferArrayShare)buf,index);
}

static void _Uint8Setter(BufferUINT8Indexed buf,unsigned int index,uint8_t element){
  * _BufferIndexer_ArrayRUint8(buf,index) = element;
}
static uint8_t _Uint8Getter(BufferUINT8Indexed buf,unsigned int index){
  return * _BufferIndexer_ArrayRUint8(buf,index);
}
static void _Uint16Setter(BufferUINT16Indexed buf,unsigned int index,uint16_t element){
  * _BufferIndexer_ArrayRUint16(buf,index) = element;
}
static uint16_t _Uint16Getter(BufferUINT16Indexed buf,unsigned int index){
  return * _BufferIndexer_ArrayRUint16(buf,index);
}
static void _Uint32Setter(BufferUINT32Indexed buf,unsigned int index,uint32_t element){
  * _BufferIndexer_ArrayRUint32(buf,index) = element;
}
static uint32_t _Uint32Getter(BufferUINT32Indexed buf,unsigned int index){
  return * _BufferIndexer_ArrayRUint32(buf,index);
}
const BUFFERINDEXED_INTERFACE _BufferIndexedInterface_ArrayRUint8 = {
  (BUFFERINTERFACE_POINTER)_Uint8Setter,
  (BUFFERINTERFACE_POINTER)_Uint8Getter
};
const BUFFERINDEXED_INTERFACE _BufferIndexedInterface_ArrayRUint16 = {
  (BUFFERINTERFACE_POINTER)_Uint16Setter,
  (BUFFERINTERFACE_POINTER)_Uint16Getter
};
const BUFFERINDEXED_INTERFACE _BufferIndexedInterface_ArrayRUint32 = {
  (BUFFERINTERFACE_POINTER)_Uint32Setter,
  (BUFFERINTERFACE_POINTER)_Uint32Getter
};

BufferExternalArrayR

BufferExternalArrayR.h

/*
*******************************************************************************************
*
*                             An Implementation for BufferArrayR
*
* File : BufferExternalArrayR.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. An implementation for BufferArrayR, which manage the array passed by user.
*          b. Inheritance tree: Container -> BufferTYPE -> BufferTYPEIndexed -> 
*             BufferTYPEArrayShare -> BufferTYPEArrayR
*                 where TYPE can be UINT8, UINT16, UINT32 ......
*             See the header file of each class to figure out which it can do.
*******************************************************************************************
*/

#ifndef _BUFFER_EXTERNAL_ARRAYR_H
#define _BUFFER_EXTERNAL_ARRAYR_H

/*
*******************************************************************************************
*                                    INCLUDES
*******************************************************************************************
*/

#include "BufferArrayR.h"

/*
*******************************************************************************************
*                                     FUNCTIONS
*******************************************************************************************
*/


// description: Create an instance of BufferArrayR
// parameters : arr        the array to be managed by the BufferArray
//              capacity   the size of the array
// return     : the instance created.
//              NULL       if anything wrong.
// note       : in the lifetime of the instance, you should never touch the array, just
//              think it as the private property of the instance
BufferUINT8ArrayR  BufferUINT8ExternalArrayR_Create (uint8_t  * __RPTR arr, unsigned int capacity);
BufferUINT16ArrayR BufferUINT16ExternalArrayR_Create(uint16_t * __RPTR arr, unsigned int capacity);
BufferUINT32ArrayR BufferUINT32ExternalArrayR_Create(uint32_t * __RPTR arr, unsigned int capacity);

#endif

BufferExternalArrayR.c

/*
*******************************************************************************************
*
*                             An Implementation for BufferArray
*
* File : BufferExternalArrayR.c
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): a. An implementation for BufferArray, which use the array passed by user.
*          b. Inheritance tree: Container -> BufferTYPE -> BufferTYPEIndexed -> 
*             BufferTYPEArrayShare -> BufferTYPEArrayR
*                 where TYPE can be UINT8, UINT16, UINT32 ......
*             See the header file of each class to figure out which it can do.
*******************************************************************************************
*/

#include <stdlib.h>
#include "BufferExternalArrayR.h"

BufferUINT8ArrayR BufferUINT8ExternalArrayR_Create(uint8_t * __RPTR arr, unsigned int capacity){
  BufferUINT8ArrayR buf = (BufferUINT8ArrayR)malloc(sizeof(BUFFERARRAYR_STRUCT));
  if(buf)
    _BufferUINT8ArrayR_Init(buf, arr,capacity,_Destroy_JustCallFree);
  return buf;
}
BufferUINT16ArrayR BufferUINT16ExternalArrayR_Create(uint16_t * __RPTR arr, unsigned int capacity){
  BufferUINT16ArrayR buf = (BufferUINT16ArrayR)malloc(sizeof(BUFFERARRAYR_STRUCT));
  if(buf)
    _BufferUINT16ArrayR_Init(buf, arr,capacity,_Destroy_JustCallFree);
  return buf;
}

BufferUINT32ArrayR BufferUINT32ExternalArrayR_Create (uint32_t * __RPTR arr, unsigned int capacity){
  BufferUINT32ArrayR buf = (BufferUINT32ArrayR)malloc(sizeof(BUFFERARRAYR_STRUCT));
  if(buf)
    _BufferUINT32ArrayR_Init(buf, arr,capacity,_Destroy_JustCallFree);
  return buf;
}

BufferChar

BufferChar.h

示例了怎么适配其他类型元素的缓冲区,由于直接使用的宏,不需要.c文件。

/*
*******************************************************************************************
*
*                                Buffer for char type
*
* File : BufferChar.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date:  2019/01/08
* version: V1.0
* History: 
* NOTE(s): Adapt BufferChar from BufferUINT8Array
*******************************************************************************************
*/

#ifndef _BUFFERCHAR_H
#define _BUFFERCHAR_H

/*
*******************************************************************************************
*                                    INCLUDES
*******************************************************************************************
*/

#include "BufferMallocArray.h"
#include "BufferExternalArray.h"

/*
*******************************************************************************************
*                              DATA TYPE    数据类型
*******************************************************************************************
*/

typedef BufferUINT8   BufferChar;

/*
*******************************************************************************************
*                                  FUNCTION PROTOTYPE
*******************************************************************************************
*/

// BufferChar BufferChar_Create(unsigned int capacity);
#define BufferChar_Create(capacity)          \
  ((BufferChar)BufferUINT8MallocArray_Create(capacity))
// BufferChar BufferChar_CreateEx(char * arr,unsigned int capacity);
#define BufferChar_CreateEx(arr,capacity)    \
  ((BufferChar)BufferUINT8ExternalArray_Create((uint8_t *)(arr),capacity))

// unsigned int BufferChar_getCapacity(BufferChar buf);
#define BufferChar_getCapacity(buf)          BufferUINT8_getCapacity(buf)

// unsigned int BufferChar_getCount(BufferChar buf);
#define BufferChar_getCount(buf)             BufferUINT8_getCount(buf)

// BOOL BufferChar_isEmpty(BufferChar buf);
#define BufferChar_isEmpty(buf)              BufferUINT8_isEmpty(buf)

// BOOL BufferChar_isFull(BufferChar buf);
#define BufferChar_isFull(buf)               BufferUINT8_isFull(buf)

// char BufferChar_Front(BufferChar buf);
#define BufferChar_Front(buf)               ((char)BufferUINT8_Front(buf))

// char BufferChar_Back(BufferChar buf);
#define BufferChar_Back(buf)                ((char)BufferUINT8_Back(buf))

// void BufferChar_FrontIn(BufferChar buf,char element);
#define BufferChar_FrontIn(buf,element)      BufferUINT8_FrontIn(buf,(uint8_t)element)

// void BufferChar_BackIn(BufferChar buf,char element);
#define BufferChar_BackIn(buf,element)       BufferUINT8_BackIn(buf,(uint8_t)element)

// char BufferChar_FrontOut(BufferChar buf);
#define BufferChar_FrontOut(buf)            ((char)BufferUINT8_FrontOut(buf))

// char BufferChar_BackOut(BufferChar buf);
#define BufferChar_BackOut(buf)             ((char)BufferUINT8_BackOut(buf))

// char BufferChar_Cleanup(BufferChar buf);
#define BufferChar_Cleanup(buf)              BufferUINT8_Cleanup(buf)

// void BufferChar_Destroy(BufferChar buf);
#define BufferChar_Destroy(buf)              BufferUINT8_Destroy(buf)

#endif

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值