3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * http://aws.amazon.com/freertos
23 * http://www.FreeRTOS.org
27 * FreeRTOS_Stream_Buffer.h
29 * A cicular character buffer
30 * An implementation of a circular buffer without a length field
31 * If LENGTH defines the size of the buffer, a maximum of (LENGT-1) bytes can be stored
32 * In order to add or read data from the buffer, memcpy() will be called at most 2 times
35 #ifndef FREERTOS_STREAM_BUFFER_H
36 #define FREERTOS_STREAM_BUFFER_H
42 typedef struct xSTREAM_BUFFER {
43 volatile size_t uxTail; /* next item to read */
44 volatile size_t uxMid; /* iterator within the valid items */
45 volatile size_t uxHead; /* next position store a new item */
46 volatile size_t uxFront; /* iterator within the free space */
47 size_t LENGTH; /* const value: number of reserved elements */
48 uint8_t ucArray[ sizeof( size_t ) ];
51 static portINLINE void vStreamBufferClear( StreamBuffer_t *pxBuffer );
52 static portINLINE void vStreamBufferClear( StreamBuffer_t *pxBuffer )
54 /* Make the circular buffer empty */
55 pxBuffer->uxHead = 0u;
56 pxBuffer->uxTail = 0u;
57 pxBuffer->uxFront = 0u;
60 /*-----------------------------------------------------------*/
62 static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper );
63 static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper )
65 /* Returns the space between uxLower and uxUpper, which equals to the distance minus 1 */
68 uxCount = pxBuffer->LENGTH + uxUpper - uxLower - 1u;
69 if( uxCount >= pxBuffer->LENGTH )
71 uxCount -= pxBuffer->LENGTH;
76 /*-----------------------------------------------------------*/
78 static portINLINE size_t uxStreamBufferDistance( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper );
79 static portINLINE size_t uxStreamBufferDistance( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper )
81 /* Returns the distance between uxLower and uxUpper */
84 uxCount = pxBuffer->LENGTH + uxUpper - uxLower;
85 if ( uxCount >= pxBuffer->LENGTH )
87 uxCount -= pxBuffer->LENGTH;
92 /*-----------------------------------------------------------*/
94 static portINLINE size_t uxStreamBufferGetSpace( const StreamBuffer_t *pxBuffer );
95 static portINLINE size_t uxStreamBufferGetSpace( const StreamBuffer_t *pxBuffer )
97 /* Returns the number of items which can still be added to uxHead
98 before hitting on uxTail */
99 size_t uxHead = pxBuffer->uxHead;
100 size_t uxTail = pxBuffer->uxTail;
102 return uxStreamBufferSpace( pxBuffer, uxHead, uxTail );
104 /*-----------------------------------------------------------*/
106 static portINLINE size_t uxStreamBufferFrontSpace( const StreamBuffer_t *pxBuffer );
107 static portINLINE size_t uxStreamBufferFrontSpace( const StreamBuffer_t *pxBuffer )
109 /* Distance between uxFront and uxTail
110 or the number of items which can still be added to uxFront,
111 before hitting on uxTail */
113 size_t uxFront = pxBuffer->uxFront;
114 size_t uxTail = pxBuffer->uxTail;
116 return uxStreamBufferSpace( pxBuffer, uxFront, uxTail );
118 /*-----------------------------------------------------------*/
120 static portINLINE size_t uxStreamBufferGetSize( const StreamBuffer_t *pxBuffer );
121 static portINLINE size_t uxStreamBufferGetSize( const StreamBuffer_t *pxBuffer )
123 /* Returns the number of items which can be read from uxTail
124 before reaching uxHead */
125 size_t uxHead = pxBuffer->uxHead;
126 size_t uxTail = pxBuffer->uxTail;
128 return uxStreamBufferDistance( pxBuffer, uxTail, uxHead );
130 /*-----------------------------------------------------------*/
132 static portINLINE size_t uxStreamBufferMidSpace( const StreamBuffer_t *pxBuffer );
133 static portINLINE size_t uxStreamBufferMidSpace( const StreamBuffer_t *pxBuffer )
135 /* Returns the distance between uxHead and uxMid */
136 size_t uxHead = pxBuffer->uxHead;
137 size_t uxMid = pxBuffer->uxMid;
139 return uxStreamBufferDistance( pxBuffer, uxMid, uxHead );
141 /*-----------------------------------------------------------*/
143 static portINLINE void vStreamBufferMoveMid( StreamBuffer_t *pxBuffer, size_t uxCount );
144 static portINLINE void vStreamBufferMoveMid( StreamBuffer_t *pxBuffer, size_t uxCount )
146 /* Increment uxMid, but no further than uxHead */
147 size_t uxSize = uxStreamBufferMidSpace( pxBuffer );
149 if( uxCount > uxSize )
153 pxBuffer->uxMid += uxCount;
154 if( pxBuffer->uxMid >= pxBuffer->LENGTH )
156 pxBuffer->uxMid -= pxBuffer->LENGTH;
159 /*-----------------------------------------------------------*/
161 static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t *pxBuffer, const size_t uxLeft, const size_t uxRight );
162 static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t *pxBuffer, const size_t uxLeft, const size_t uxRight )
165 size_t uxTail = pxBuffer->uxTail;
167 /* Returns true if ( uxLeft < uxRight ) */
168 if( ( uxLeft < uxTail ) ^ ( uxRight < uxTail ) )
170 if( uxRight < uxTail )
181 if( uxLeft <= uxRight )
192 /*-----------------------------------------------------------*/
194 static portINLINE size_t uxStreamBufferGetPtr( StreamBuffer_t *pxBuffer, uint8_t **ppucData );
195 static portINLINE size_t uxStreamBufferGetPtr( StreamBuffer_t *pxBuffer, uint8_t **ppucData )
197 size_t uxNextTail = pxBuffer->uxTail;
198 size_t uxSize = uxStreamBufferGetSize( pxBuffer );
200 *ppucData = pxBuffer->ucArray + uxNextTail;
202 return FreeRTOS_min_uint32( uxSize, pxBuffer->LENGTH - uxNextTail );
206 * Add bytes to a stream buffer.
208 * pxBuffer - The buffer to which the bytes will be added.
209 * uxOffset - If uxOffset > 0, data will be written at an offset from uxHead
210 * while uxHead will not be moved yet.
211 * pucData - A pointer to the data to be added.
212 * uxCount - The number of bytes to add.
214 size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxCount );
217 * Read bytes from a stream buffer.
219 * pxBuffer - The buffer from which the bytes will be read.
220 * uxOffset - Can be used to read data located at a certain offset from 'uxTail'.
221 * pucData - A pointer to the buffer into which data will be read.
222 * uxMaxCount - The number of bytes to read.
223 * xPeek - If set to pdTRUE the data will remain in the buffer.
225 size_t uxStreamBufferGet( StreamBuffer_t *pxBuffer, size_t uxOffset, uint8_t *pucData, size_t uxMaxCount, BaseType_t xPeek );
231 #endif /* !defined( FREERTOS_STREAM_BUFFER_H ) */