VxWorks操作系统环形缓冲队列rngLib的移植使用

一、rngLib的源码

rngLib.h

/* rngLib.h - ring buffer subroutine library header */


/* Copyright 1984-2004 Wind River Systems, Inc. */


/*
modification history
--------------------
02e,22oct04,aeg  removed rngCreateKernel() and rngDeleteKernel() (SPR #102956)
02d,23mar04,job  Removed special handling of STDC for function prototypes
02c,20jan04,dat  Adding rngCreateKernel for 88437
02b,22sep92,rrr  added support for c++
02a,04jul92,jcf  cleaned up.
01k,26may92,rrr  the tree shuffle
01j,04oct91,rrr  passed through the ansification filter
      -changed VOID to void
      -changed copyright notice
01i,06apr91,gae  added NOMANUAL to avoid fooling mangen.
01h,05oct90,shl  added ANSI function prototypes.
                 made #endif ANSI style.
                 added copyright notice.
01g,10aug90,dnw  added declaration of rngFlush().
01f,07aug90,shl  moved function declarations to end of file.
01e,22aug88,gae  removed incorrect comment about using 'shorts'
     for optimization.
01d,30may88,dnw  changed to v4 names.
01c,10nov87,dnw  changed ring pointers from shorts to ints.
     rings can now be > 32K bytes.
01b,15aug84,dnw  removed several macros, now routines in rngLib.cs;
       only rngGetC and rngPutC remain as macros.
01a,06jun84,dnw  culled from old drvLib.h
*/


#ifndef __INCrngLibh
#define __INCrngLibh


#ifdef __cplusplus
extern "C" {
#endif




/* HIDDEN */


/* typedefs */


typedef struct    /* RING - ring buffer */
    {
    int pToBuf;    /* offset from start of buffer where to write next */
    int pFromBuf;  /* offset from start of buffer where to read next */
    int bufSize;  /* size of ring in bytes */
    char *buf;    /* pointer to start of buffer */
    } RING;


/* END_HIDDEN */


typedef RING *RING_ID;




/*
 * The following macros are designed to do various operations on
 * the RING object.  By using them, users can avoid having to know
 * the structure of RING.  However they are intended to be very
 * efficient and this is why they are macros in the first place.
 * In general the parameters to them should be register variables
 * for maximum efficiency.
 */


/*******************************************************************************
*
* RNG_ELEM_GET - get one character from a ring buffer
*
* This macro gets a single character from the specified ring buffer.
* Must supply temporary variable (register int) 'fromP'.
*
* RETURNS: 1 if there was a char in the buffer to return, 0 otherwise
*
* NOMANUAL
*/


#define RNG_ELEM_GET(ringId, pCh, fromP)    \
    (            \
    fromP = (ringId)->pFromBuf,      \
    ((ringId)->pToBuf == fromP) ?    \
  0           \
    :            \
  (          \
  *pCh = (ringId)->buf[fromP],    \
  (ringId)->pFromBuf = ((++fromP == (ringId)->bufSize) ? 0 : fromP), \
  1          \
  )          \
    )


/*******************************************************************************
*
* RNG_ELEM_PUT - put one character into a ring buffer
*
* This macro puts a single character into the specified ring buffer.
* Must supply temporary variable (register int) 'toP'.
*
* RETURNS: 1 if there was room in the buffer for the char, 0 otherwise
*
* NOMANUAL
*/


#define RNG_ELEM_PUT(ringId, ch, toP)    \
    (            \
    toP = (ringId)->pToBuf,      \
    (toP == (ringId)->pFromBuf - 1) ?    \
  0           \
    :            \
  (          \
      (toP == (ringId)->bufSize - 1) ?  \
      (          \
      ((ringId)->pFromBuf == 0) ?    \
    0        \
      :          \
    (        \
    (ringId)->buf[toP] = ch,  \
    (ringId)->pToBuf = 0,    \
    1        \
    )        \
      )          \
  :          \
      (          \
      (ringId)->buf[toP] = ch,    \
      (ringId)->pToBuf++,      \
      1          \
      )          \
  )          \
    )


/* function declarations */


extern BOOL   rngIsEmpty (RING_ID ringId);
extern BOOL   rngIsFull (RING_ID ringId);
extern RING_ID   rngCreate (int nbytes);
extern int   rngBufGet (RING_ID rngId, char *buffer, int maxbytes);
extern int   rngBufPut (RING_ID rngId, char *buffer, int nbytes);
extern int   rngFreeBytes (RING_ID ringId);
extern int   rngNBytes (RING_ID ringId);
extern void   rngDelete (RING_ID ringId);
extern void   rngFlush (RING_ID ringId);
extern void   rngMoveAhead (RING_ID ringId, int n);
extern void   rngPutAhead (RING_ID ringId, char byte, int offset);


#ifdef __cplusplus
}
#endif


#endif /* __INCrngLibh */

rngLib.c

/* rngLib.c - ring buffer subroutine library */


/* Copyright 1984-1995 Wind River Systems, Inc. */
#include "copyright_wrs.h"


/*
modification history
--------------------
01x,13feb95,jdi  doc tweaks.
01w,20jan93,jdi  documentation cleanup for 5.1.
01v,26may92,rrr  the tree shuffle
01u,11jan92,wmd  fix bug spr #1210, race condition based on updates of buf
     pointers in more than 1 place in rngBufPut() and rngBufGet().
01t,13dec91,gae  ANSI cleanup.
01s,04oct91,rrr  passed through the ansification filter
                  -changed functions to ansi style
      -changed VOID to void
      -changed copyright notice
01r,05apr91,jdi   documentation -- removed header parens and x-ref numbers;
     doc review by dnw.
01q,11mar91,jaa   documentation cleanup.
01p,11may90,yao  added missing modification history (01o) for the last checkin.
01o,09may90,yao  typecasted malloc to (char *).
01n,22mar89,dab  changed shorts to ints in rngBufGet, rngBufPut.
01m,03feb89,dab  added rngDelete to delete a ring buffer.
01l,20aug88,gae  documentation.
01k,07jul88,jcf  fixed malloc to match new declaration.
01j,30may88,dnw  changed to v4 names.
01i,03nov87,ecs  documentation.
01h,20oct87,gae  documentation.
01g,23mar87,jlf  documentation.
01f,21dec86,dnw  changed to not get include files from default directories.
01e,14apr86,rdc  changed memAllocates to mallocs.
01d,20jul85,jlf  documentation.
01c,09sep84,jlf  added comments and copyright.
01b,15aug84,dnw  changed rngBufCreate to allocate ring buffer one byte larger
       than requested, because ring buffer algorithm always leaves
       at least one empty byte in buffer.
     added rngEmpty, rngFull, rngFreeBytes, rngNBytes, rngFlush,
       rngPutAhead, rngMoveAhead, some of which used to be
       macros in rngLib.h.
     changed rngBufGet,rngBufPut to rngGetBuf,rngPutBuf.
     changed rngBufCreate to rngCreate.
01a,06jun84,dnw  culled from old drvLib.c
*/


/*
This library provides routines for creating and using ring buffers, which
are first-in-first-out circular buffers.  The routines simply manipulate
the ring buffer data structure; no kernel functions are invoked.  In
particular, ring buffers by themselves provide no task synchronization or
mutual exclusion.


However, the ring buffer pointers are manipulated in such a way that a
reader task (invoking rngBufGet()) and a writer task (invoking
rngBufPut()) can access a ring simultaneously without requiring mutual
exclusion.  This is because readers only affect a \f2read\f1 pointer and
writers only affect a \f2write\f1 pointer in a ring buffer data structure.
However, access by multiple readers or writers \f2must\fP be interlocked
through a mutual exclusion mechanism (i.e., a mutual-exclusion semaphore
guarding a ring buffer).




This library also supplies two macros, RNG_ELEM_PUT and RNG_ELEM_GET,
for putting and getting single bytes from a ring buffer.  They are defined
in rngLib.h.
.CS
    int RNG_ELEM_GET (ringId, pch, fromP)
    int RNG_ELEM_PUT (ringId, ch, toP)
.CE
Both macros require a temporary variable <fromP> or <toP>, which
should be declared as `register int' for maximum efficiency.  RNG_ELEM_GET
returns 1 if there was a character available in the buffer; it returns 0
otherwise.  RNG_ELEM_PUT returns 1 if there was room in the buffer; it returns
0 otherwise.  These are somewhat faster than rngBufPut() and rngBufGet(),
which can put and get multi-byte buffers.


INCLUDE FILES: rngLib.h
*/


/* LINTLIBRARY */


#include "vxWorks.h"
#include "memLib.h"
#include "rngLib.h"
#include "stdlib.h"
#include "string.h"


/*******************************************************************************
*
* rngCreate - create an empty ring buffer
*
* This routine creates a ring buffer of size <nbytes>, and initializes
* it.  Memory for the buffer is allocated from the system memory partition.
*
* RETURNS
* The ID of the ring buffer, or NULL if memory cannot be allocated.
*/


RING_ID rngCreate
    (
    int nbytes          /* number of bytes in ring buffer */
    )
    {
    char *buffer;
    RING_ID ringId = (RING_ID) malloc (sizeof (RING));


    if (ringId == NULL)
  return (NULL);


    /* bump number of bytes requested because ring buffer algorithm
     * always leaves at least one empty byte in buffer */


    buffer = (char *) malloc ((unsigned) ++nbytes);


    if (buffer == NULL)
  {
  free ((char *)ringId);
  return (NULL);
  }


    ringId->bufSize = nbytes;
    ringId->buf      = buffer;


    rngFlush (ringId);


    return (ringId);
    }
/*******************************************************************************
*
* rngDelete - delete a ring buffer
*
* This routine deletes a specified ring buffer.
* Any data currently in the buffer will be lost.
*
* RETURNS: N/A
*/


void rngDelete
    (
    FAST RING_ID ringId         /* ring buffer to delete */
    )
    {
    free (ringId->buf);
    free ((char *)ringId);
    }
/*******************************************************************************
*
* rngFlush - make a ring buffer empty
*
* This routine initializes a specified ring buffer to be empty.
* Any data currently in the buffer will be lost.
*
* RETURNS: N/A
*/


void rngFlush
    (
    FAST RING_ID ringId         /* ring buffer to initialize */
    )
    {
    ringId->pToBuf   = 0;
    ringId->pFromBuf = 0;
    }
/*******************************************************************************
*
* rngBufGet - get characters from a ring buffer
*
* This routine copies bytes from the ring buffer <rngId> into <buffer>.
* It copies as many bytes as are available in the ring, up to <maxbytes>.
* The bytes copied will be removed from the ring.
*
* RETURNS:
* The number of bytes actually received from the ring buffer;
* it may be zero if the ring buffer is empty at the time of the call.
*/


int rngBufGet
    (
    FAST RING_ID rngId,         /* ring buffer to get data from      */
    char *buffer,               /* pointer to buffer to receive data */
    int maxbytes                /* maximum number of bytes to get    */
    )
    {
    FAST int bytesgot = 0;
    int pToBuf = rngId->pToBuf;
    int bytes2;
    int pRngTmp = 0;


    if (pToBuf >= rngId->pFromBuf)
  {
  /* pToBuf has not wrapped around */


  bytesgot = min (maxbytes, pToBuf - rngId->pFromBuf);
  bcopy (&rngId->buf [rngId->pFromBuf], buffer, bytesgot);
  rngId->pFromBuf += bytesgot;
  }
    else
  {
  /* pToBuf has wrapped around.  Grab chars up to the end of the
   * buffer, then wrap around if we need to. */


  bytesgot = min (maxbytes, rngId->bufSize - rngId->pFromBuf);
  bcopy (&rngId->buf [rngId->pFromBuf], buffer, bytesgot);
  pRngTmp = rngId->pFromBuf + bytesgot;


  /* If pFromBuf is equal to bufSize, we've read the entire buffer,
   * and need to wrap now.  If bytesgot < maxbytes, copy some more chars
   * in now. */


  if (pRngTmp == rngId->bufSize)
      {
      bytes2 = min (maxbytes - bytesgot, pToBuf);
      bcopy (rngId->buf, buffer + bytesgot, bytes2);
      rngId->pFromBuf = bytes2;
      bytesgot += bytes2;
      }
  else
      rngId->pFromBuf = pRngTmp;
  }
    return (bytesgot);
    }
/*******************************************************************************
*
* rngBufPut - put bytes into a ring buffer
*
* This routine puts bytes from <buffer> into ring buffer <ringId>.  The
* specified number of bytes will be put into the ring, up to the number of
* bytes available in the ring.
*
* INTERNAL
* Always leaves at least one byte empty between pToBuf and pFromBuf, to
* eliminate ambiguities which could otherwise occur when the two pointers
* are equal.
*
* RETURNS:
* The number of bytes actually put into the ring buffer;
* it may be less than number requested, even zero,
* if there is insufficient room in the ring buffer at the time of the call.
*/


int rngBufPut
    (
    FAST RING_ID rngId,         /* ring buffer to put data into  */
    char *buffer,               /* buffer to get data from       */
    int nbytes                  /* number of bytes to try to put */
    )
    {
    FAST int bytesput = 0;
    int pFromBuf = rngId->pFromBuf;
    int bytes2;
    int pRngTmp = 0;


    if (pFromBuf > rngId->pToBuf)
  {
  /* pFromBuf is ahead of pToBuf.  We can fill up to two bytes
   * before it */


  bytesput = min (nbytes, pFromBuf - rngId->pToBuf - 1);
  bcopy (buffer, &rngId->buf [rngId->pToBuf], bytesput);
  rngId->pToBuf += bytesput;
  }
    else if (pFromBuf == 0)
  {
  /* pFromBuf is at the beginning of the buffer.  We can fill till
   * the next-to-last element */


  bytesput = min (nbytes, rngId->bufSize - rngId->pToBuf - 1);
  bcopy (buffer, &rngId->buf [rngId->pToBuf], bytesput);
  rngId->pToBuf += bytesput;
  }
    else
  {
  /* pFromBuf has wrapped around, and its not 0, so we can fill
   * at least to the end of the ring buffer.  Do so, then see if
   * we need to wrap and put more at the beginning of the buffer. */


  bytesput = min (nbytes, rngId->bufSize - rngId->pToBuf);
  bcopy (buffer, &rngId->buf [rngId->pToBuf], bytesput);
  pRngTmp = rngId->pToBuf + bytesput;


  if (pRngTmp == rngId->bufSize)
      {
      /* We need to wrap, and perhaps put some more chars */


      bytes2 = min (nbytes - bytesput, pFromBuf - 1);
      bcopy (buffer + bytesput, rngId->buf, bytes2);
      rngId->pToBuf = bytes2;
      bytesput += bytes2;
      }
  else
      rngId->pToBuf = pRngTmp;
  }
    return (bytesput);
    }
/*******************************************************************************
*
* rngIsEmpty - test if a ring buffer is empty
*
* This routine determines if a specified ring buffer is empty.
*
* RETURNS:
* TRUE if empty, FALSE if not.
*/


BOOL rngIsEmpty
    (
    RING_ID ringId      /* ring buffer to test */
    )
    {
    return (ringId->pToBuf == ringId->pFromBuf);
    }
/*******************************************************************************
*
* rngIsFull - test if a ring buffer is full (no more room)
*
* This routine determines if a specified ring buffer is completely full.
*
* RETURNS:
* TRUE if full, FALSE if not.
*/


BOOL rngIsFull
    (
    FAST RING_ID ringId         /* ring buffer to test */
    )
    {
    int n = ringId->pToBuf - ringId->pFromBuf + 1;


    return ((n == 0) || (n == ringId->bufSize));
    }
/*******************************************************************************
*
* rngFreeBytes - determine the number of free bytes in a ring buffer
*
* This routine determines the number of bytes currently unused in a specified
* ring buffer.
*
* RETURNS: The number of unused bytes in the ring buffer.
*/


int rngFreeBytes
    (
    FAST RING_ID ringId         /* ring buffer to examine */
    )
    {
    FAST int n = ringId->pFromBuf - ringId->pToBuf - 1;


    if (n < 0)
  n += ringId->bufSize;


    return (n);
    }
/*******************************************************************************
*
* rngNBytes - determine the number of bytes in a ring buffer
*
* This routine determines the number of bytes currently in a specified
* ring buffer.
*
* RETURNS: The number of bytes filled in the ring buffer.
*/


int rngNBytes
    (
    FAST RING_ID ringId         /* ring buffer to be enumerated */
    )
    {
    FAST int n = ringId->pToBuf - ringId->pFromBuf;


    if (n < 0)
  n += ringId->bufSize;


    return (n);
    }
/*******************************************************************************
*
* rngPutAhead - put a byte ahead in a ring buffer without moving ring pointers
*
* This routine writes a byte into the ring, but does not move the ring buffer
* pointers.  Thus the byte will not yet be available to rngBufGet() calls.
* The byte is written <offset> bytes ahead of the next input location in the
* ring.  Thus, an offset of 0 puts the byte in the same position as would
* RNG_ELEM_PUT would put a byte, except that the input pointer is not updated.
*
* Bytes written ahead in the ring buffer with this routine can be made available
* all at once by subsequently moving the ring buffer pointers with the routine
* rngMoveAhead().
*
* Before calling rngPutAhead(), the caller must verify that at least
* <offset> + 1 bytes are available in the ring buffer.
*
* RETURNS: N/A
*/


void rngPutAhead
    (
    FAST RING_ID ringId,   /* ring buffer to put byte in    */
    char byte,             /* byte to be put in ring        */
    int offset             /* offset beyond next input byte where to put byte */
    )
    {
    FAST int n = ringId->pToBuf + offset;


    if (n >= ringId->bufSize)
  n -= ringId->bufSize;


    *(ringId->buf + n) = byte;
    }
/*******************************************************************************
*
* rngMoveAhead - advance a ring pointer by <n> bytes
*
* This routine advances the ring buffer input pointer by <n> bytes.  This makes
* <n> bytes available in the ring buffer, after having been written ahead in
* the ring buffer with rngPutAhead().
*
* RETURNS: N/A
*/


void rngMoveAhead
    (
    FAST RING_ID ringId,  /* ring buffer to be advanced                  */
    FAST int n            /* number of bytes ahead to move input pointer */
    )
    {
    n += ringId->pToBuf;


    if (n >= ringId->bufSize)
  n -= ringId->bufSize;


    ringId->pToBuf = n;
    }

二、移植

新建工程,只需要将rngLib.c和rngLib.h添加到工程中即可。

①屏蔽掉rngLib.c文件中没有引用的头文件

//#include "copyright_wrs.h"
//#include "vxWorks.h"
//#include "memLib.h"

②rngLib.c文件中添加宏定义

#define min(i, j) (((i) < (j)) ? (i) : (j))
#define max(i, j) (((i) > (j)) ? (i) : (j))

③去掉FAST

④将BOOL类型改为int类型

修改后的c和h文件如下:

/* rngLib.c - ring buffer subroutine library */


/* Copyright 1984-1995 Wind River Systems, Inc. */
//#include "copyright_wrs.h"




/*
modification history
--------------------
01x,13feb95,jdi  doc tweaks.
01w,20jan93,jdi  documentation cleanup for 5.1.
01v,26may92,rrr  the tree shuffle
01u,11jan92,wmd  fix bug spr #1210, race condition based on updates of buf
     pointers in more than 1 place in rngBufPut() and rngBufGet().
01t,13dec91,gae  ANSI cleanup.
01s,04oct91,rrr  passed through the ansification filter
                  -changed functions to ansi style
      -changed VOID to void
      -changed copyright notice
01r,05apr91,jdi   documentation -- removed header parens and x-ref numbers;
     doc review by dnw.
01q,11mar91,jaa   documentation cleanup.
01p,11may90,yao  added missing modification history (01o) for the last checkin.
01o,09may90,yao  typecasted malloc to (char *).
01n,22mar89,dab  changed shorts to ints in rngBufGet, rngBufPut.
01m,03feb89,dab  added rngDelete to delete a ring buffer.
01l,20aug88,gae  documentation.
01k,07jul88,jcf  fixed malloc to match new declaration.
01j,30may88,dnw  changed to v4 names.
01i,03nov87,ecs  documentation.
01h,20oct87,gae  documentation.
01g,23mar87,jlf  documentation.
01f,21dec86,dnw  changed to not get include files from default directories.
01e,14apr86,rdc  changed memAllocates to mallocs.
01d,20jul85,jlf  documentation.
01c,09sep84,jlf  added comments and copyright.
01b,15aug84,dnw  changed rngBufCreate to allocate ring buffer one byte larger
       than requested, because ring buffer algorithm always leaves
       at least one empty byte in buffer.
     added rngEmpty, rngFull, rngFreeBytes, rngNBytes, rngFlush,
       rngPutAhead, rngMoveAhead, some of which used to be
       macros in rngLib.h.
     changed rngBufGet,rngBufPut to rngGetBuf,rngPutBuf.
     changed rngBufCreate to rngCreate.
01a,06jun84,dnw  culled from old drvLib.c
*/


/*
This library provides routines for creating and using ring buffers, which
are first-in-first-out circular buffers.  The routines simply manipulate
the ring buffer data structure; no kernel functions are invoked.  In
particular, ring buffers by themselves provide no task synchronization or
mutual exclusion.


However, the ring buffer pointers are manipulated in such a way that a
reader task (invoking rngBufGet()) and a writer task (invoking
rngBufPut()) can access a ring simultaneously without requiring mutual
exclusion.  This is because readers only affect a \f2read\f1 pointer and
writers only affect a \f2write\f1 pointer in a ring buffer data structure.
However, access by multiple readers or writers \f2must\fP be interlocked
through a mutual exclusion mechanism (i.e., a mutual-exclusion semaphore
guarding a ring buffer).




This library also supplies two macros, RNG_ELEM_PUT and RNG_ELEM_GET,
for putting and getting single bytes from a ring buffer.  They are defined
in rngLib.h.
.CS
    int RNG_ELEM_GET (ringId, pch, fromP)
    int RNG_ELEM_PUT (ringId, ch, toP)
.CE
Both macros require a temporary variable <fromP> or <toP>, which
should be declared as `register int' for maximum efficiency.  RNG_ELEM_GET
returns 1 if there was a character available in the buffer; it returns 0
otherwise.  RNG_ELEM_PUT returns 1 if there was room in the buffer; it returns
0 otherwise.  These are somewhat  er than rngBufPut() and rngBufGet(),
which can put and get multi-byte buffers.


INCLUDE FILES: rngLib.h
*/


/* LINTLIBRARY */


//#include "vxWorks.h"
//#include "memLib.h"
#include "rngLib.h"
#include "stdlib.h"
#include "string.h"


#define min(i, j) (((i) < (j)) ? (i) : (j))
#define max(i, j) (((i) > (j)) ? (i) : (j))


/*******************************************************************************
*
* rngCreate - create an empty ring buffer
*
* This routine creates a ring buffer of size <nbytes>, and initializes
* it.  Memory for the buffer is allocated from the system memory partition.
*
* RETURNS
* The ID of the ring buffer, or NULL if memory cannot be allocated.
*/


RING_ID rngCreate
    (
    int nbytes          /* number of bytes in ring buffer */
    )
    {
    char *buffer;
    RING_ID ringId = (RING_ID) malloc (sizeof (RING));


    if (ringId == NULL)
  return (NULL);


    /* bump number of bytes requested because ring buffer algorithm
     * always leaves at least one empty byte in buffer */


    buffer = (char *) malloc ((unsigned) ++nbytes);


    if (buffer == NULL)
  {
  free ((char *)ringId);
  return (NULL);
  }


    ringId->bufSize = nbytes;
    ringId->buf      = buffer;


    rngFlush (ringId);


    return (ringId);
    }
/*******************************************************************************
*
* rngDelete - delete a ring buffer
*
* This routine deletes a specified ring buffer.
* Any data currently in the buffer will be lost.
*
* RETURNS: N/A
*/


void rngDelete
    (
      RING_ID ringId         /* ring buffer to delete */
    )
    {
    free (ringId->buf);
    free ((char *)ringId);
    }
/*******************************************************************************
*
* rngFlush - make a ring buffer empty
*
* This routine initializes a specified ring buffer to be empty.
* Any data currently in the buffer will be lost.
*
* RETURNS: N/A
*/


void rngFlush
    (
      RING_ID ringId         /* ring buffer to initialize */
    )
    {
    ringId->pToBuf   = 0;
    ringId->pFromBuf = 0;
    }
/*******************************************************************************
*
* rngBufGet - get characters from a ring buffer
*
* This routine copies bytes from the ring buffer <rngId> into <buffer>.
* It copies as many bytes as are available in the ring, up to <maxbytes>.
* The bytes copied will be removed from the ring.
*
* RETURNS:
* The number of bytes actually received from the ring buffer;
* it may be zero if the ring buffer is empty at the time of the call.
*/


int rngBufGet
    (
      RING_ID rngId,         /* ring buffer to get data from      */
    char *buffer,               /* pointer to buffer to receive data */
    int maxbytes                /* maximum number of bytes to get    */
    )
    {
      int bytesgot = 0;
    int pToBuf = rngId->pToBuf;
    int bytes2;
    int pRngTmp = 0;


    if (pToBuf >= rngId->pFromBuf)
  {
  /* pToBuf has not wrapped around */


  bytesgot = min (maxbytes, pToBuf - rngId->pFromBuf);
  bcopy (&rngId->buf [rngId->pFromBuf], buffer, bytesgot);
  rngId->pFromBuf += bytesgot;
  }
    else
  {
  /* pToBuf has wrapped around.  Grab chars up to the end of the
   * buffer, then wrap around if we need to. */


  bytesgot = min (maxbytes, rngId->bufSize - rngId->pFromBuf);
  bcopy (&rngId->buf [rngId->pFromBuf], buffer, bytesgot);
  pRngTmp = rngId->pFromBuf + bytesgot;


  /* If pFromBuf is equal to bufSize, we've read the entire buffer,
   * and need to wrap now.  If bytesgot < maxbytes, copy some more chars
   * in now. */


  if (pRngTmp == rngId->bufSize)
      {
      bytes2 = min (maxbytes - bytesgot, pToBuf);
      bcopy (rngId->buf, buffer + bytesgot, bytes2);
      rngId->pFromBuf = bytes2;
      bytesgot += bytes2;
      }
  else
      rngId->pFromBuf = pRngTmp;
  }
    return (bytesgot);
    }
/*******************************************************************************
*
* rngBufPut - put bytes into a ring buffer
*
* This routine puts bytes from <buffer> into ring buffer <ringId>.  The
* specified number of bytes will be put into the ring, up to the number of
* bytes available in the ring.
*
* INTERNAL
* Always leaves at least one byte empty between pToBuf and pFromBuf, to
* eliminate ambiguities which could otherwise occur when the two pointers
* are equal.
*
* RETURNS:
* The number of bytes actually put into the ring buffer;
* it may be less than number requested, even zero,
* if there is insufficient room in the ring buffer at the time of the call.
*/


int rngBufPut
    (
      RING_ID rngId,         /* ring buffer to put data into  */
    char *buffer,               /* buffer to get data from       */
    int nbytes                  /* number of bytes to try to put */
    )
    {
      int bytesput = 0;
    int pFromBuf = rngId->pFromBuf;
    int bytes2;
    int pRngTmp = 0;


    if (pFromBuf > rngId->pToBuf)
  {
  /* pFromBuf is ahead of pToBuf.  We can fill up to two bytes
   * before it */


  bytesput = min (nbytes, pFromBuf - rngId->pToBuf - 1);
  bcopy (buffer, &rngId->buf [rngId->pToBuf], bytesput);
  rngId->pToBuf += bytesput;
  }
    else if (pFromBuf == 0)
  {
  /* pFromBuf is at the beginning of the buffer.  We can fill till
   * the next-to-last element */


  bytesput = min (nbytes, rngId->bufSize - rngId->pToBuf - 1);
  bcopy (buffer, &rngId->buf [rngId->pToBuf], bytesput);
  rngId->pToBuf += bytesput;
  }
    else
  {
  /* pFromBuf has wrapped around, and its not 0, so we can fill
   * at least to the end of the ring buffer.  Do so, then see if
   * we need to wrap and put more at the beginning of the buffer. */


  bytesput = min (nbytes, rngId->bufSize - rngId->pToBuf);
  bcopy (buffer, &rngId->buf [rngId->pToBuf], bytesput);
  pRngTmp = rngId->pToBuf + bytesput;


  if (pRngTmp == rngId->bufSize)
      {
      /* We need to wrap, and perhaps put some more chars */


      bytes2 = min (nbytes - bytesput, pFromBuf - 1);
      bcopy (buffer + bytesput, rngId->buf, bytes2);
      rngId->pToBuf = bytes2;
      bytesput += bytes2;
      }
  else
      rngId->pToBuf = pRngTmp;
  }
    return (bytesput);
    }
/*******************************************************************************
*
* rngIsEmpty - test if a ring buffer is empty
*
* This routine determines if a specified ring buffer is empty.
*
* RETURNS:
* TRUE if empty, FALSE if not.
*/


int rngIsEmpty
    (
    RING_ID ringId      /* ring buffer to test */
    )
    {
    return (ringId->pToBuf == ringId->pFromBuf);
    }
/*******************************************************************************
*
* rngIsFull - test if a ring buffer is full (no more room)
*
* This routine determines if a specified ring buffer is completely full.
*
* RETURNS:
* TRUE if full, FALSE if not.
*/


int rngIsFull
    (
      RING_ID ringId         /* ring buffer to test */
    )
    {
    int n = ringId->pToBuf - ringId->pFromBuf + 1;


    return ((n == 0) || (n == ringId->bufSize));
    }
/*******************************************************************************
*
* rngFreeBytes - determine the number of free bytes in a ring buffer
*
* This routine determines the number of bytes currently unused in a specified
* ring buffer.
*
* RETURNS: The number of unused bytes in the ring buffer.
*/


int rngFreeBytes
    (
      RING_ID ringId         /* ring buffer to examine */
    )
    {
      int n = ringId->pFromBuf - ringId->pToBuf - 1;


    if (n < 0)
  n += ringId->bufSize;


    return (n);
    }
/*******************************************************************************
*
* rngNBytes - determine the number of bytes in a ring buffer
*
* This routine determines the number of bytes currently in a specified
* ring buffer.
*
* RETURNS: The number of bytes filled in the ring buffer.
*/


int rngNBytes
    (
      RING_ID ringId         /* ring buffer to be enumerated */
    )
    {
      int n = ringId->pToBuf - ringId->pFromBuf;


    if (n < 0)
  n += ringId->bufSize;


    return (n);
    }
/*******************************************************************************
*
* rngPutAhead - put a byte ahead in a ring buffer without moving ring pointers
*
* This routine writes a byte into the ring, but does not move the ring buffer
* pointers.  Thus the byte will not yet be available to rngBufGet() calls.
* The byte is written <offset> bytes ahead of the next input location in the
* ring.  Thus, an offset of 0 puts the byte in the same position as would
* RNG_ELEM_PUT would put a byte, except that the input pointer is not updated.
*
* Bytes written ahead in the ring buffer with this routine can be made available
* all at once by subsequently moving the ring buffer pointers with the routine
* rngMoveAhead().
*
* Before calling rngPutAhead(), the caller must verify that at least
* <offset> + 1 bytes are available in the ring buffer.
*
* RETURNS: N/A
*/


void rngPutAhead
    (
      RING_ID ringId,   /* ring buffer to put byte in    */
    char byte,             /* byte to be put in ring        */
    int offset             /* offset beyond next input byte where to put byte */
    )
    {
      int n = ringId->pToBuf + offset;


    if (n >= ringId->bufSize)
  n -= ringId->bufSize;


    *(ringId->buf + n) = byte;
    }
/*******************************************************************************
*
* rngMoveAhead - advance a ring pointer by <n> bytes
*
* This routine advances the ring buffer input pointer by <n> bytes.  This makes
* <n> bytes available in the ring buffer, after having been written ahead in
* the ring buffer with rngPutAhead().
*
* RETURNS: N/A
*/


void rngMoveAhead
    (
      RING_ID ringId,  /* ring buffer to be advanced                  */
      int n            /* number of bytes ahead to move input pointer */
    )
    {
    n += ringId->pToBuf;


    if (n >= ringId->bufSize)
  n -= ringId->bufSize;


    ringId->pToBuf = n;
    }
/* rngLib.h - ring buffer subroutine library header */


/* Copyright 1984-2004 Wind River Systems, Inc. */


/*
modification history
--------------------
02e,22oct04,aeg  removed rngCreateKernel() and rngDeleteKernel() (SPR #102956)
02d,23mar04,job  Removed special handling of STDC for function prototypes
02c,20jan04,dat  Adding rngCreateKernel for 88437
02b,22sep92,rrr  added support for c++
02a,04jul92,jcf  cleaned up.
01k,26may92,rrr  the tree shuffle
01j,04oct91,rrr  passed through the ansification filter
      -changed VOID to void
      -changed copyright notice
01i,06apr91,gae  added NOMANUAL to avoid fooling mangen.
01h,05oct90,shl  added ANSI function prototypes.
                 made #endif ANSI style.
                 added copyright notice.
01g,10aug90,dnw  added declaration of rngFlush().
01f,07aug90,shl  moved function declarations to end of file.
01e,22aug88,gae  removed incorrect comment about using 'shorts'
     for optimization.
01d,30may88,dnw  changed to v4 names.
01c,10nov87,dnw  changed ring pointers from shorts to ints.
     rings can now be > 32K bytes.
01b,15aug84,dnw  removed several macros, now routines in rngLib.cs;
       only rngGetC and rngPutC remain as macros.
01a,06jun84,dnw  culled from old drvLib.h
*/


#ifndef __INCrngLibh
#define __INCrngLibh


#ifdef __cplusplus
extern "C" {
#endif




/* HIDDEN */


/* typedefs */


typedef struct    /* RING - ring buffer */
    {
    int pToBuf;    /* offset from start of buffer where to write next */
    int pFromBuf;  /* offset from start of buffer where to read next */
    int bufSize;  /* size of ring in bytes */
    char *buf;    /* pointer to start of buffer */
    } RING;


/* END_HIDDEN */


typedef RING *RING_ID;


/*
 * The following macros are designed to do various operations on
 * the RING object.  By using them, users can avoid having to know
 * the structure of RING.  However they are intended to be very
 * efficient and this is why they are macros in the first place.
 * In general the parameters to them should be register variables
 * for maximum efficiency.
 */


/*******************************************************************************
*
* RNG_ELEM_GET - get one character from a ring buffer
*
* This macro gets a single character from the specified ring buffer.
* Must supply temporary variable (register int) 'fromP'.
*
* RETURNS: 1 if there was a char in the buffer to return, 0 otherwise
*
* NOMANUAL
*/


#define RNG_ELEM_GET(ringId, pCh, fromP)    \
    (            \
    fromP = (ringId)->pFromBuf,      \
    ((ringId)->pToBuf == fromP) ?    \
  0           \
    :            \
  (          \
  *pCh = (ringId)->buf[fromP],    \
  (ringId)->pFromBuf = ((++fromP == (ringId)->bufSize) ? 0 : fromP), \
  1          \
  )          \
    )


/*******************************************************************************
*
* RNG_ELEM_PUT - put one character into a ring buffer
*
* This macro puts a single character into the specified ring buffer.
* Must supply temporary variable (register int) 'toP'.
*
* RETURNS: 1 if there was room in the buffer for the char, 0 otherwise
*
* NOMANUAL
*/


#define RNG_ELEM_PUT(ringId, ch, toP)    \
    (            \
    toP = (ringId)->pToBuf,      \
    (toP == (ringId)->pFromBuf - 1) ?    \
  0           \
    :            \
  (          \
      (toP == (ringId)->bufSize - 1) ?  \
      (          \
      ((ringId)->pFromBuf == 0) ?    \
    0        \
      :          \
    (        \
    (ringId)->buf[toP] = ch,  \
    (ringId)->pToBuf = 0,    \
    1        \
    )        \
      )          \
  :          \
      (          \
      (ringId)->buf[toP] = ch,    \
      (ringId)->pToBuf++,      \
      1          \
      )          \
  )          \
    )


/* function declarations */


extern int   rngIsEmpty (RING_ID ringId);//空
extern int   rngIsFull (RING_ID ringId);//满
extern RING_ID   rngCreate (int nbytes);//创建
extern int   rngBufGet (RING_ID rngId, char *buffer, int maxbytes);//读取
extern int   rngBufPut (RING_ID rngId, char *buffer, int nbytes);//发送
extern int   rngFreeBytes (RING_ID ringId);//剩余
extern int   rngNBytes (RING_ID ringId);//使用
extern void   rngDelete (RING_ID ringId);//删除
extern void   rngFlush (RING_ID ringId);//刷新
extern void   rngMoveAhead (RING_ID ringId, int n);
extern void   rngPutAhead (RING_ID ringId, char byte, int offset);


#ifdef __cplusplus
}
#endif


#endif /* __INCrngLibh */

三、测试

测试代码:

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




int main(int argv,char *argc[])
{
    char bufSend[]="hello world";
    char bufRx[20]={0};
    RING_ID id;
    int i=0;;
    id=rngCreate(100);
    if(id==NULL)
        return -1;
    while(1)
    {
        if(rngIsFull(id))
        {
            rngFlush(id);
            //break;
            continue;
        }
        rngBufPut(id,bufSend,strlen(bufSend));
        printf("i=%d\n",++i);
        printf("使用=%d\n",rngNBytes(id));
        printf("剩余=%d\n",rngFreeBytes(id));
        rngBufGet(id,bufRx,sizeof(bufRx));
        printf("%s\n",bufRx);
        memset(bufRx,0,sizeof(bufRx));
        sleep(3);


    }
    rngDelete(id);
    return 0;
}

测试结果:

8d626a848c01ec46a69090de548535c6.png

欢迎关注公众号:嵌入式学习与实践

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值