文章目录
要使用这个模块,得先放入Buffer类相关代码,详见前几篇博客。
Queue
Queue.h
/*
*******************************************************************************************
*
* Parent Class for All Queue
*
* File : Queue.h
* By : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date: 2019/02/16
* version: V1.0
* History:
* NOTE(s): a. Queue is defined here as a FIFO(First In First Out) struct, which has In
* and Out methods. It's inherited from Container class.
*******************************************************************************************
*/
#ifndef _QUEUE_H
#define _QUEUE_H
/*
*******************************************************************************************
* DATA TYPE
*******************************************************************************************
*/
typedef struct QUEUE_STRUCT * Queue;
typedef struct QUEUEUINT8_STRUCT * QueueUINT8;
typedef struct QUEUEUINT16_STRUCT * QueueUINT16;
typedef struct QUEUEUINT32_STRUCT * QueueUINT32;
#include "Container.h"
typedef void (* QUEUEINTERFACE_VOID)(Queue);
typedef void (* QUEUEUINT8INTERFACE_VOID)(QueueUINT8);
typedef void (* QUEUEUINT16INTERFACE_VOID)(QueueUINT16);
typedef void (* QUEUEUINT32INTERFACE_VOID)(QueueUINT32);
typedef void (* QUEUEUINT8INTERFACE_TAKEELEMENT)(QueueUINT8,uint8_t);
typedef void (* QUEUEUINT16INTERFACE_TAKEELEMENT)(QueueUINT16,uint16_t);
typedef void (* QUEUEUINT32INTERFACE_TAKEELEMENT)(QueueUINT32,uint32_t);
typedef uint8_t (* QUEUEUINT8INTERFACE_RETURNELEMENT)(QueueUINT8);
typedef uint16_t (* QUEUEUINT16INTERFACE_RETURNELEMENT)(QueueUINT16);
typedef uint32_t (* QUEUEUINT32INTERFACE_RETURNELEMENT)(QueueUINT32);
/*
*******************************************************************************************
* CONSTANT
*******************************************************************************************
*/
// default return value when any error in methods of child class
#define QUEUE_WHENERR_ELEMENTRETURN -1
/*
*******************************************************************************************
* INTERFACE FOR ALL QUEUE CLASS
*******************************************************************************************
*/
// unsigned int Queue_getCapacity(Queue que);
// return: capacity of the Queue que
// 0 when que == NULL
#define Queue_getCapacity(que) Container_getCapacity((Container)(que))
// unsigned int Queue_getCount(Queue que);
// return: element count of the Queue que
// 0 when que == NULL
#define Queue_getCount(que) Container_getCount((Container)(que))
// BOOL Queue_isEmpty(Queue que);
// return: whether the Queue que is empty
// TRUE when que == NULL
#define Queue_isEmpty(que) Container_isEmpty((Container)(que))
// BOOL Queue_isFull(Queue que);
// return: whether the Queue que is full
// FALSE when que == NULL
#define Queue_isFull(que) Container_isFull((Container)(que))
// void Queue_Destroy(Queue que);
// destroy the Queue que
#define Queue_Destroy(que) Container_Destroy((Container)(que))
// cleanup the Queue que
void Queue_Cleanup(Queue que);
/*
*******************************************************************************************
* INTERFACE FOR UINT8 QUEUE
*******************************************************************************************
*/
// unsigned int QueueUINT8_getCapacity(QueueUINT8 que);
#define QueueUINT8_getCapacity(que) Queue_getCapacity((Queue)que)
// unsigned int QueueUINT8_getCount(QueueUINT8 que);
#define QueueUINT8_getCount(que) Queue_getCount((Queue)que)
// BOOL QueueUINT8_isEmpty(QueueUINT8 que);
#define QueueUINT8_isEmpty(que) Queue_isEmpty((Queue)que)
// BOOL QueueUINT8_isFull(QueueUINT8 que);
#define QueueUINT8_isFull(que) Queue_isFull((Queue)que)
// void QueueUINT8_Destroy(QueueUINT8 que);
#define QueueUINT8_Destroy(que) Queue_Destroy((Queue)que)
// put an element to the queue.
// if container is full, the behavior depends on the implementation.
void QueueUINT8_In (QueueUINT8 que,uint8_t element);
// pick an element from the queue.
// return QUEUE_WHENERR_ELEMENTRETURN when any error
uint8_t QueueUINT8_Out (QueueUINT8 que);
#define QueueUINT8_Cleanup(que) Queue_Cleanup((Queue)que)
/*
*******************************************************************************************
* INTERFACE FOR UINT16 QUEUE
*******************************************************************************************
*/
// unsigned int QueueUINT16_getCapacity(QueueUINT16 que);
#define QueueUINT16_getCapacity(que) Queue_getCapacity((Queue)que)
// unsigned int QueueUINT16_getCount(QueueUINT16 que);
#define QueueUINT16_getCount(que) Queue_getCount((Queue)que)
// BOOL QueueUINT16_isEmpty(QueueUINT16 que);
#define QueueUINT16_isEmpty(que) Queue_isEmpty((Queue)que)
// BOOL QueueUINT16_isFull(QueueUINT16 que);
#define QueueUINT16_isFull(que) Queue_isFull((Queue)que)
// void QueueUINT16_Destroy(QueueUINT16 que);
#define QueueUINT16_Destroy(que) Queue_Destroy((Queue)que)
// put an element to the queue.
// if container is full, the behavior depends on the implementation.
void QueueUINT16_In (QueueUINT16 que,uint16_t element);
// pick an element from the queue.
// return QUEUE_WHENERR_ELEMENTRETURN when any error
uint16_t QueueUINT16_Out (QueueUINT16 que);
#define QueueUINT16_Cleanup(que) Queue_Cleanup((Queue)que)
/*
*******************************************************************************************
* INTERFACE FOR UINT32 QUEUE
*******************************************************************************************
*/
// unsigned int QueueUINT32_getCapacity(QueueUINT32 que);
#define QueueUINT32_getCapacity(que) Queue_getCapacity((Queue)que)
// unsigned int QueueUINT32_getCount(QueueUINT32 que);
#define QueueUINT32_getCount(que) Queue_getCount((Queue)que)
// BOOL QueueUINT32_isEmpty(QueueUINT32 que);
#define QueueUINT32_isEmpty(que) Queue_isEmpty((Queue)que)
// BOOL QueueUINT32_isFull(QueueUINT32 que);
#define QueueUINT32_isFull(que) Queue_isFull((Queue)que)
// void QueueUINT32_Destroy(QueueUINT32 que);
#define QueueUINT32_Destroy(que) Queue_Destroy((Queue)que)
// put an element to the queue.
// if container is full, the behavior depends on the implementation.
void QueueUINT32_In (QueueUINT32 que,uint32_t element);
// pick an element from the queue.
// return QUEUE_WHENERR_ELEMENTRETURN when any error
uint32_t QueueUINT32_Out (QueueUINT32 que);
#define QueueUINT32_Cleanup(que) Queue_Cleanup((Queue)que)
#include "QueuePrivate.h"
#endif
QueuePrivate.h
/*
*******************************************************************************************
*
* Parent Class for All Queue
*
* File : QueuePrivate.h
* By : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date: 2019/02/16
* 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 Queue of all
* type. All Queue Objects have the same shape interfaces (in the virtual
* table) following the exact same order below:
*
* void QueueXXXX_In (Queue que, ElementType element);
* ElementType QueueXXXX_Out (Queue que);
* void QueueXXXX_Cleanup(Queue que);
*
* Different ElementTypes lead to different function signatures, however, due to
* the exact same order, we know which one is the "In" function of all function.
* d. If you want to add a Queue Class of new ElementType, you need to implement
* some methods to guide compiler to correct function signatures, just like
* uint8_t QueueUINT8_Out(QueueUINT8 buf);
* do. You can use Implementations of QueueUINT8 Interface as a template to
* create yours.
* e. If you want to write an implementation for QueueUINT8 Class, for example.
* the main work you should do is to inherit from the Queue Class, implement
* the CONTAINER_INTERFACE and QUEUE_INTERFACE. And when creating the instance,
* assign the virtual table. (see _Queue_Init() below)
* 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 Queue Class,
* whose element type take the same space as your new type, rather than create
* interfaces for new type. e.g,QueueChar can be adapted from QueueUINT8.
* 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 In method when full ,and Out method when empty, are !!!
* !!! undefined. It depends on the impelementation !!!
*******************************************************************************************
*/
#include "Queue.h"
/*
*******************************************************************************************
* PROTECTED INTERFACES
*******************************************************************************************
*/
typedef const struct QUEUE_INTERFACE * QUEUE_INTERFACE_TABLE;
typedef const struct QUEUEUINT8_INTERFACE * QUEUEUINT8_INTERFACE_TABLE;
typedef const struct QUEUEUINT16_INTERFACE * QUEUEUINT16_INTERFACE_TABLE;
typedef const struct QUEUEUINT32_INTERFACE * QUEUEUINT32_INTERFACE_TABLE;
typedef struct QUEUE_STRUCT{
CONTAINER_STRUCT parent;
union{
QUEUE_INTERFACE_TABLE v;
QUEUEUINT8_INTERFACE_TABLE uint8;
QUEUEUINT16_INTERFACE_TABLE uint16;
QUEUEUINT32_INTERFACE_TABLE uint32;
} vtable;
}QUEUE_STRUCT;
#define _Queue_mVtable(que) (((Queue)(que))->vtable.v)
#define _Queue_fIn(que) (_Queue_mVtable(que)->in)
#define _Queue_fOut(que) (_Queue_mVtable(que)->out)
#define _Queue_fCleanup(que) (_Queue_mVtable(que)->cleanup)
typedef struct QUEUEUINT8_STRUCT{
QUEUE_STRUCT member;
}QUEUEUINT8_STRUCT;
#define _QueueUINT8_mVtable(que) (((Queue)(que))->vtable.uint8)
#define _QueueUINT8_fIn(que) (_QueueUINT8_mVtable(que)->in)
#define _QueueUINT8_fOut(que) (_QueueUINT8_mVtable(que)->out)
#define _QueueUINT8_fCleanup(que) (_QueueUINT8_mVtable(que)->cleanup)
typedef struct QUEUEUINT16_STRUCT{
QUEUE_STRUCT member;
}QUEUEUINT16_STRUCT;
#define _QueueUINT16_mVtable(que) (((Queue)(que))->vtable.uint16)
#define _QueueUINT16_fIn(que) (_QueueUINT16_mVtable(que)->in)
#define _QueueUINT16_fOut(que) (_QueueUINT16_mVtable(que)->out)
#define _QueueUINT16_fCleanup(que) (_QueueUINT16_mVtable(que)->cleanup)
typedef struct QUEUEUINT32_STRUCT{
QUEUE_STRUCT member;
}QUEUEUINT32_STRUCT;
#define _QueueUINT32_mVtable(que) (((Queue)(que))->vtable.uint32)
#define _QueueUINT32_fIn(que) (_QueueUINT32_mVtable(que)->in)
#define _QueueUINT32_fOut(que) (_QueueUINT32_mVtable(que)->out)
#define _QueueUINT32_fCleanup(que) (_QueueUINT32_mVtable(que)->cleanup)
typedef void (* QUEUEINTERFACE_POINTER)(void);
typedef struct QUEUE_INTERFACE{
QUEUEINTERFACE_POINTER in; // the que passed in is assured not NULL
QUEUEINTERFACE_POINTER out; // the que passed in is assured not NULL
QUEUEINTERFACE_VOID cleanup; // the que passed in is assured not NULL
} QUEUE_INTERFACE;
typedef struct QUEUEUINT8_INTERFACE{
QUEUEUINT8INTERFACE_TAKEELEMENT in; // the que passed in is assured not NULL
QUEUEUINT8INTERFACE_RETURNELEMENT out; // the que passed in is assured not NULL
QUEUEUINT8INTERFACE_VOID cleanup; // the que passed in is assured not NULL
} QUEUEUINT8_INTERFACE;
typedef struct QUEUEUINT16_INTERFACE{
QUEUEUINT16INTERFACE_TAKEELEMENT in; // the que passed in is assured not NULL
QUEUEUINT16INTERFACE_RETURNELEMENT out; // the que passed in is assured not NULL
QUEUEUINT16INTERFACE_VOID cleanup; // the que passed in is assured not NULL
} QUEUEUINT16_INTERFACE;
typedef struct QUEUEUINT32_INTERFACE{
QUEUEUINT32INTERFACE_TAKEELEMENT in; // the que passed in is assured not NULL
QUEUEUINT32INTERFACE_RETURNELEMENT out; // the que passed in is assured not NULL
QUEUEUINT32INTERFACE_VOID cleanup; // the que passed in is assured not NULL
} QUEUEUINT32_INTERFACE;
/*
*******************************************************************************************
* PROTECTED MEMBER AND METHOD
*******************************************************************************************
*/
// initialize a Queue instance(internal, no NULL check)
// void _Queue_Init(Queue que,OBJECTINTERFACE_VOID fDestroy,CONTAINER_INTERFACE_TABLE c_vtable,
// QUEUE_INTERFACE_TABLE vtable);
#define _Queue_Init(que,fDestroy,c_vtable,vtable) \
{ _Container_Init(que,fDestroy,c_vtable); \
_Queue_mVtable(que) = vtable; }
// destroy method member of the quefer(internal, no NULL check)
#define _Queue_fDestroy(que) (_Container_fDestroy((Container)(que)))
#define _Queue_getCapacity(que) _Container_getCapacity((Container)(que))
#define _Queue_getCount(que) _Container_getCount((Container)(que))
// whether the quefer is empty(internal, no NULL check)
#define _Queue_isEmpty(que) _Container_isEmpty((Container)(que))
// whether the quefer is full(internal, no NULL check)
#define _Queue_isFull(que) _Container_isFull((Container)(que))
//BOOL _Queue_isNullorEmpty(Queue que);
#define _Queue_isNullorEmpty(que) _Container_isNullorEmpty((Container)(que))
//BOOL _Queue_isNullorFull(Queue que);
#define _Queue_isNullorFull(que) _Container_isNullorFull((Container)(que))
Queue.c
/*
*******************************************************************************************
*
* Common Methods for All Queue Class and implementations for UINT8, UINT16, UINT32
*
* File : Queue.c
* By : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date: 2019/02/16
* version: V1.0
* History:
* NOTE(s): 1. we assume every queue should implement the (whole) vtable, so there is no
* NULL check for vtable and the method. (if a child class don't implementation
* a method and leave it NULL, and it happens to be called, then ,just let it
* crash!! hhhhh)
*******************************************************************************************
*/
#include "Queue.h"
/*
*******************************************************************************************
* PUBLIC METHOD IMPLEMENTATIONS
*******************************************************************************************
*/
void Queue_Cleanup(Queue que){
if(que == NULL)
return;
_Queue_fCleanup(que)(que);
}
void QueueUINT8_In(QueueUINT8 que,uint8_t element){
if(que == NULL)
return;
_QueueUINT8_fIn(que)(que,element);
}
uint8_t QueueUINT8_Out(QueueUINT8 que){
if(que == NULL)
return QUEUE_WHENERR_ELEMENTRETURN;
return _QueueUINT8_fOut(que)(que);
}
void QueueUINT16_In(QueueUINT16 que,uint16_t element){
if(que == NULL)
return;
_QueueUINT16_fIn(que)(que,element);
}
uint16_t QueueUINT16_Out(QueueUINT16 que){
if(que == NULL)
return QUEUE_WHENERR_ELEMENTRETURN;
return _QueueUINT16_fOut(que)(que);
}
void QueueUINT32_In(QueueUINT32 que,uint32_t element){
if(que == NULL)
return;
_QueueUINT32_fIn(que)(que,element);
}
uint32_t QueueUINT32_Out(QueueUINT32 que){
if(que == NULL)
return QUEUE_WHENERR_ELEMENTRETURN;
return _QueueUINT32_fOut(que)(que);
}
BufferToQueueAdapter
BufferToQueueAdapter.h
/*
*******************************************************************************************
*
* Create a Queue from a Buffer
*
* File : BufferToQueueAdapter.h
* By : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date: 2019/02/16
* version: V1.0
* History:
* NOTE(s): a. This Adapter is to adapt a Buffer instance to a Queue instance
* b. once you has adapted a Buffer instance to Queue, you should think the
* instance private to the new created Queue instance and never use it,
* the new instance will destroy the buffer instance when destroyed.
*******************************************************************************************
*/
#ifndef _BUFFERTOQUEUEADAPTER_H
#define _BUFFERTOQUEUEADAPTER_H
#include "Buffer.h"
#include "Queue.h"
/*
*******************************************************************************************
* INTERFACE
*******************************************************************************************
*/
// create a queue instance from a buffer instance
// return : the new created queue instance.
// NULL if any error.
// note : if success, you should never use the buffer instance.
QueueUINT8 BufferToQueueAdapter_CreateUINT8 (BufferUINT8 buf);
QueueUINT16 BufferToQueueAdapter_CreateUINT16(BufferUINT16 buf);
QueueUINT32 BufferToQueueAdapter_CreateUINT32(BufferUINT32 buf);
#endif
BufferToQueueAdapter.c
/*
*******************************************************************************************
*
* Create a Queue from a Buffer Implementation
*
* File : BufferToQueueAdapter.c
* By : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date: 2019/02/16
* version: V1.0
* History:
* NOTE(s): the main work of this adapter is to provide interface to redirect the call to
* the method of queue to the corresponding buffer method.
* Queue_getCapacity --> Buffer_getCapacity
* Queue_getCount --> Buffer_getCount
* Queue_In --> Buffer_BackIn
* Queue_Out --> Buffer_FrontOut
* Queue_Cleanup --> Buffer_Cleanup
*******************************************************************************************
*/
#include "BufferToQueueAdapter.h"
#include <stdlib.h>
/*
*******************************************************************************************
* DATA STRUCT DEFINITION
*******************************************************************************************
*/
typedef struct QUEUEFROMBUFFER_STRUCT{
QUEUE_STRUCT parent;
Buffer buf;
}QUEUEFROMBUFFER_STRUCT, *QueueFromBuffer;
#define _QueueFromBuffer_mBuf(que) (((QueueFromBuffer)que)->buf)
#define _mBuf(que) _QueueFromBuffer_mBuf(que)
/*
*******************************************************************************************
* INTERFACE IMPLEMENTATIONS
*******************************************************************************************
*/
static void _cleanup(Queue que){
_Buffer_fCleanup(_mBuf(que))(_mBuf(que));
}
static void uint8_in(QueueUINT8 que,uint8_t element){
((BUFFERUINT8INTERFACE_TAKEELEMENT)_BufferUINT8_fBackIn(_mBuf(que)))
((BufferUINT8)_mBuf(que),element);
}
static uint8_t uint8_out(QueueUINT8 que){
return ((BUFFERUINT8INTERFACE_RETURNELEMENT)_BufferUINT8_fFrontOut(_mBuf(que)))((BufferUINT8)_mBuf(que));
}
static const QUEUEUINT8_INTERFACE queueuint8_interface = {
uint8_in,
uint8_out,
(QUEUEUINT8INTERFACE_VOID)_cleanup
};
static void uint16_in(QueueUINT16 que,uint16_t element){
((BUFFERUINT16INTERFACE_TAKEELEMENT)_BufferUINT16_fBackIn(_mBuf(que)))
((BufferUINT16)_mBuf(que),element);
}
static uint16_t uint16_out(QueueUINT16 que){
return ((BUFFERUINT16INTERFACE_RETURNELEMENT)_BufferUINT16_fFrontOut(_mBuf(que)))((BufferUINT16)_mBuf(que));
}
static const QUEUEUINT16_INTERFACE queueuint16_interface = {
uint16_in,
uint16_out,
(QUEUEUINT16INTERFACE_VOID)_cleanup
};
static void uint32_in(QueueUINT32 que,uint32_t element){
((BUFFERUINT32INTERFACE_TAKEELEMENT)_BufferUINT32_fBackIn(_mBuf(que)))
((BufferUINT32)_mBuf(que),element);
}
static uint32_t uint32_out(QueueUINT32 que){
return ((BUFFERUINT32INTERFACE_RETURNELEMENT)_BufferUINT32_fFrontOut(_mBuf(que)))((BufferUINT32)_mBuf(que));
}
static const QUEUEUINT32_INTERFACE queueuint32_interface = {
uint32_in,
uint32_out,
(QUEUEUINT32INTERFACE_VOID)_cleanup
};
static unsigned int _getCapacity(Container ct){
return _Buffer_getCapacity(_mBuf(ct));
}
static unsigned int _getCount(Container ct){
return _Buffer_getCount(_mBuf(ct));
}
static const CONTAINER_INTERFACE _container_interface = {
_getCapacity,
_getCount
};
static void _destroy(void * q){
if(q){
Buffer_Destroy(_mBuf(q));
free(q);
}
}
/*
*******************************************************************************************
* PUBLIC METHOD IMPLEMENTATIONS
*******************************************************************************************
*/
QueueUINT8 BufferToQueueAdapter_CreateUINT8(BufferUINT8 buf){
QueueFromBuffer q;
if(buf == NULL || (q = (QueueFromBuffer)malloc(sizeof(QUEUEFROMBUFFER_STRUCT))) == NULL)
return NULL;
_mBuf(q) = (Buffer)buf;
_Queue_Init(q,_destroy,&_container_interface,(QUEUE_INTERFACE_TABLE)&queueuint8_interface);
return (QueueUINT8)q;
}
QueueUINT16 BufferToQueueAdapter_CreateUINT16(BufferUINT16 buf){
QueueFromBuffer q;
if(buf == NULL || (q = (QueueFromBuffer)malloc(sizeof(QUEUEFROMBUFFER_STRUCT))) == NULL)
return NULL;
_mBuf(q) = (Buffer)buf;
_Queue_Init(q,_destroy,&_container_interface,(QUEUE_INTERFACE_TABLE)&queueuint16_interface);
return (QueueUINT16)q;
}
QueueUINT32 BufferToQueueAdapter_CreateUINT32(BufferUINT32 buf){
QueueFromBuffer q;
if(buf == NULL || (q = (QueueFromBuffer)malloc(sizeof(QUEUEFROMBUFFER_STRUCT))) == NULL)
return NULL;
_mBuf(q) = (Buffer)buf;
_Queue_Init(q,_destroy,&_container_interface,(QUEUE_INTERFACE_TABLE)&queueuint32_interface);
return (QueueUINT32)q;
}