]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Stream_Buffer.h
1ebb86d8d19ebba4b2f7756473157687d94f3bfb
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / include / FreeRTOS_Stream_Buffer.h
1 /*\r
2  * FreeRTOS+TCP V2.0.11\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://aws.amazon.com/freertos\r
23  * http://www.FreeRTOS.org\r
24  */\r
25 \r
26 /*\r
27  *      FreeRTOS_Stream_Buffer.h\r
28  *\r
29  *      A cicular character buffer\r
30  *      An implementation of a circular buffer without a length field\r
31  *      If LENGTH defines the size of the buffer, a maximum of (LENGT-1) bytes can be stored\r
32  *      In order to add or read data from the buffer, memcpy() will be called at most 2 times\r
33  */\r
34 \r
35 #ifndef FREERTOS_STREAM_BUFFER_H\r
36 #define FREERTOS_STREAM_BUFFER_H\r
37 \r
38 #ifdef __cplusplus\r
39 extern "C" {\r
40 #endif\r
41 \r
42 typedef struct xSTREAM_BUFFER {\r
43         volatile size_t uxTail;         /* next item to read */\r
44         volatile size_t uxMid;          /* iterator within the valid items */\r
45         volatile size_t uxHead;         /* next position store a new item */\r
46         volatile size_t uxFront;        /* iterator within the free space */\r
47         size_t LENGTH;                          /* const value: number of reserved elements */\r
48         uint8_t ucArray[ sizeof( size_t ) ];\r
49 } StreamBuffer_t;\r
50 \r
51 static portINLINE void vStreamBufferClear( StreamBuffer_t *pxBuffer );\r
52 static portINLINE void vStreamBufferClear( StreamBuffer_t *pxBuffer )\r
53 {\r
54         /* Make the circular buffer empty */\r
55         pxBuffer->uxHead = 0u;\r
56         pxBuffer->uxTail = 0u;\r
57         pxBuffer->uxFront = 0u;\r
58         pxBuffer->uxMid = 0u;\r
59 }\r
60 /*-----------------------------------------------------------*/\r
61 \r
62 static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper );\r
63 static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper )\r
64 {\r
65 /* Returns the space between uxLower and uxUpper, which equals to the distance minus 1 */\r
66 size_t uxCount;\r
67 \r
68         uxCount = pxBuffer->LENGTH + uxUpper - uxLower - 1u;\r
69         if( uxCount >= pxBuffer->LENGTH )\r
70         {\r
71                 uxCount -= pxBuffer->LENGTH;\r
72         }\r
73 \r
74         return uxCount;\r
75 }\r
76 /*-----------------------------------------------------------*/\r
77 \r
78 static portINLINE size_t uxStreamBufferDistance( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper );\r
79 static portINLINE size_t uxStreamBufferDistance( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper )\r
80 {\r
81 /* Returns the distance between uxLower and uxUpper */\r
82 size_t uxCount;\r
83 \r
84         uxCount = pxBuffer->LENGTH + uxUpper - uxLower;\r
85         if ( uxCount >= pxBuffer->LENGTH )\r
86         {\r
87                 uxCount -= pxBuffer->LENGTH;\r
88         }\r
89 \r
90         return uxCount;\r
91 }\r
92 /*-----------------------------------------------------------*/\r
93 \r
94 static portINLINE size_t uxStreamBufferGetSpace( const StreamBuffer_t *pxBuffer );\r
95 static portINLINE size_t uxStreamBufferGetSpace( const StreamBuffer_t *pxBuffer )\r
96 {\r
97 /* Returns the number of items which can still be added to uxHead\r
98 before hitting on uxTail */\r
99 size_t uxHead = pxBuffer->uxHead;\r
100 size_t uxTail = pxBuffer->uxTail;\r
101 \r
102         return uxStreamBufferSpace( pxBuffer, uxHead, uxTail );\r
103 }\r
104 /*-----------------------------------------------------------*/\r
105 \r
106 static portINLINE size_t uxStreamBufferFrontSpace( const StreamBuffer_t *pxBuffer );\r
107 static portINLINE size_t uxStreamBufferFrontSpace( const StreamBuffer_t *pxBuffer )\r
108 {\r
109 /* Distance between uxFront and uxTail\r
110 or the number of items which can still be added to uxFront,\r
111 before hitting on uxTail */\r
112 \r
113 size_t uxFront = pxBuffer->uxFront;\r
114 size_t uxTail = pxBuffer->uxTail;\r
115 \r
116         return uxStreamBufferSpace( pxBuffer, uxFront, uxTail );\r
117 }\r
118 /*-----------------------------------------------------------*/\r
119 \r
120 static portINLINE size_t uxStreamBufferGetSize( const StreamBuffer_t *pxBuffer );\r
121 static portINLINE size_t uxStreamBufferGetSize( const StreamBuffer_t *pxBuffer )\r
122 {\r
123 /* Returns the number of items which can be read from uxTail\r
124 before reaching uxHead */\r
125 size_t uxHead = pxBuffer->uxHead;\r
126 size_t uxTail = pxBuffer->uxTail;\r
127 \r
128         return uxStreamBufferDistance( pxBuffer, uxTail, uxHead );\r
129 }\r
130 /*-----------------------------------------------------------*/\r
131 \r
132 static portINLINE size_t uxStreamBufferMidSpace( const StreamBuffer_t *pxBuffer );\r
133 static portINLINE size_t uxStreamBufferMidSpace( const StreamBuffer_t *pxBuffer )\r
134 {\r
135 /* Returns the distance between uxHead and uxMid */\r
136 size_t uxHead = pxBuffer->uxHead;\r
137 size_t uxMid = pxBuffer->uxMid;\r
138 \r
139         return uxStreamBufferDistance( pxBuffer, uxMid, uxHead );\r
140 }\r
141 /*-----------------------------------------------------------*/\r
142 \r
143 static portINLINE void vStreamBufferMoveMid( StreamBuffer_t *pxBuffer, size_t uxCount );\r
144 static portINLINE void vStreamBufferMoveMid( StreamBuffer_t *pxBuffer, size_t uxCount )\r
145 {\r
146 /* Increment uxMid, but no further than uxHead */\r
147 size_t uxSize = uxStreamBufferMidSpace( pxBuffer );\r
148 \r
149         if( uxCount > uxSize )\r
150         {\r
151                 uxCount = uxSize;\r
152         }\r
153         pxBuffer->uxMid += uxCount;\r
154         if( pxBuffer->uxMid >= pxBuffer->LENGTH )\r
155         {\r
156                 pxBuffer->uxMid -= pxBuffer->LENGTH;\r
157         }\r
158 }\r
159 /*-----------------------------------------------------------*/\r
160 static portINLINE BaseType_t xStreamBufferIsEmpty( const StreamBuffer_t *pxBuffer );\r
161 static portINLINE BaseType_t xStreamBufferIsEmpty( const StreamBuffer_t *pxBuffer )\r
162 {\r
163 BaseType_t xReturn;\r
164 \r
165         /* True if no item is available */\r
166         if( pxBuffer->uxHead == pxBuffer->uxTail )\r
167         {\r
168                 xReturn = pdTRUE;\r
169         }\r
170         else\r
171         {\r
172                 xReturn = pdFALSE;\r
173         }\r
174         return xReturn;\r
175 }\r
176 /*-----------------------------------------------------------*/\r
177 \r
178 static portINLINE BaseType_t xStreamBufferIsFull( const StreamBuffer_t *pxBuffer );\r
179 static portINLINE BaseType_t xStreamBufferIsFull( const StreamBuffer_t *pxBuffer )\r
180 {\r
181         /* True if the available space equals zero. */\r
182         return ( BaseType_t ) ( uxStreamBufferGetSpace( pxBuffer ) == 0u );\r
183 }\r
184 /*-----------------------------------------------------------*/\r
185 \r
186 static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t *pxBuffer, const size_t uxLeft, const size_t uxRight );\r
187 static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t *pxBuffer, const size_t uxLeft, const size_t uxRight )\r
188 {\r
189 BaseType_t xReturn;\r
190 size_t uxTail = pxBuffer->uxTail;\r
191 \r
192         /* Returns true if ( uxLeft < uxRight ) */\r
193         if( ( uxLeft < uxTail ) ^ ( uxRight < uxTail ) )\r
194         {\r
195                 if( uxRight < uxTail )\r
196                 {\r
197                         xReturn = pdTRUE;\r
198                 }\r
199                 else\r
200                 {\r
201                         xReturn = pdFALSE;\r
202                 }\r
203         }\r
204         else\r
205         {\r
206                 if( uxLeft <= uxRight )\r
207                 {\r
208                         xReturn = pdTRUE;\r
209                 }\r
210                 else\r
211                 {\r
212                         xReturn = pdFALSE;\r
213                 }\r
214         }\r
215         return xReturn;\r
216 }\r
217 /*-----------------------------------------------------------*/\r
218 \r
219 static portINLINE size_t uxStreamBufferGetPtr( StreamBuffer_t *pxBuffer, uint8_t **ppucData );\r
220 static portINLINE size_t uxStreamBufferGetPtr( StreamBuffer_t *pxBuffer, uint8_t **ppucData )\r
221 {\r
222 size_t uxNextTail = pxBuffer->uxTail;\r
223 size_t uxSize = uxStreamBufferGetSize( pxBuffer );\r
224 \r
225         *ppucData = pxBuffer->ucArray + uxNextTail;\r
226 \r
227         return FreeRTOS_min_uint32( uxSize, pxBuffer->LENGTH - uxNextTail );\r
228 }\r
229 \r
230 /*\r
231  * Add bytes to a stream buffer.\r
232  *\r
233  * pxBuffer -   The buffer to which the bytes will be added.\r
234  * uxOffset -   If uxOffset > 0, data will be written at an offset from uxHead\r
235  *                              while uxHead will not be moved yet.\r
236  * pucData -    A pointer to the data to be added.\r
237  * uxCount -    The number of bytes to add.\r
238  */\r
239 size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxCount );\r
240 \r
241 /*\r
242  * Read bytes from a stream buffer.\r
243  *\r
244  * pxBuffer -   The buffer from which the bytes will be read.\r
245  * uxOffset -   Can be used to read data located at a certain offset from 'uxTail'.\r
246  * pucData -    A pointer to the buffer into which data will be read.\r
247  * uxMaxCount - The number of bytes to read.\r
248  * xPeek -              If set to pdTRUE the data will remain in the buffer.\r
249  */\r
250 size_t uxStreamBufferGet( StreamBuffer_t *pxBuffer, size_t uxOffset, uint8_t *pucData, size_t uxMaxCount, BaseType_t xPeek );\r
251 \r
252 #ifdef __cplusplus\r
253 } /* extern "C" */\r
254 #endif\r
255 \r
256 #endif  /* !defined( FREERTOS_STREAM_BUFFER_H ) */\r