FreeRTOS_Stream_Buffer.h 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * FreeRTOS+TCP V2.3.2 LTS Patch 1
  3. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  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:
  11. *
  12. * The above copyright notice and this permission notice shall be included in all
  13. * copies or substantial portions of the Software.
  14. *
  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.
  21. *
  22. * http://aws.amazon.com/freertos
  23. * http://www.FreeRTOS.org
  24. */
  25. /*
  26. * FreeRTOS_Stream_Buffer.h
  27. *
  28. * A circular character buffer
  29. * An implementation of a circular buffer without a length field
  30. * If LENGTH defines the size of the buffer, a maximum of (LENGTH-1) bytes can be stored
  31. * In order to add or read data from the buffer, memcpy() will be called at most 2 times
  32. */
  33. #ifndef FREERTOS_STREAM_BUFFER_H
  34. #define FREERTOS_STREAM_BUFFER_H
  35. #ifdef __cplusplus
  36. extern "C" {
  37. #endif
  38. /**
  39. * structure to store all the details of a stream buffer.
  40. */
  41. typedef struct xSTREAM_BUFFER
  42. {
  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 ) ]; /**< array big enough to store any pointer address */
  49. } StreamBuffer_t;
  50. static portINLINE void vStreamBufferClear( StreamBuffer_t * pxBuffer );
  51. static portINLINE void vStreamBufferClear( StreamBuffer_t * pxBuffer )
  52. {
  53. /* Make the circular buffer empty */
  54. pxBuffer->uxHead = 0U;
  55. pxBuffer->uxTail = 0U;
  56. pxBuffer->uxFront = 0U;
  57. pxBuffer->uxMid = 0U;
  58. }
  59. /*-----------------------------------------------------------*/
  60. static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t * pxBuffer,
  61. const size_t uxLower,
  62. const size_t uxUpper );
  63. static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t * pxBuffer,
  64. const size_t uxLower,
  65. const size_t uxUpper )
  66. {
  67. /* Returns the space between uxLower and uxUpper, which equals to the distance minus 1 */
  68. size_t uxCount;
  69. uxCount = pxBuffer->LENGTH + uxUpper - uxLower - 1U;
  70. if( uxCount >= pxBuffer->LENGTH )
  71. {
  72. uxCount -= pxBuffer->LENGTH;
  73. }
  74. return uxCount;
  75. }
  76. /*-----------------------------------------------------------*/
  77. static portINLINE size_t uxStreamBufferDistance( const StreamBuffer_t * pxBuffer,
  78. const size_t uxLower,
  79. const size_t uxUpper );
  80. static portINLINE size_t uxStreamBufferDistance( const StreamBuffer_t * pxBuffer,
  81. const size_t uxLower,
  82. const size_t uxUpper )
  83. {
  84. /* Returns the distance between uxLower and uxUpper */
  85. size_t uxCount;
  86. uxCount = pxBuffer->LENGTH + uxUpper - uxLower;
  87. if( uxCount >= pxBuffer->LENGTH )
  88. {
  89. uxCount -= pxBuffer->LENGTH;
  90. }
  91. return uxCount;
  92. }
  93. /*-----------------------------------------------------------*/
  94. static portINLINE size_t uxStreamBufferGetSpace( const StreamBuffer_t * pxBuffer );
  95. static portINLINE size_t uxStreamBufferGetSpace( const StreamBuffer_t * pxBuffer )
  96. {
  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;
  101. return uxStreamBufferSpace( pxBuffer, uxHead, uxTail );
  102. }
  103. /*-----------------------------------------------------------*/
  104. static portINLINE size_t uxStreamBufferFrontSpace( const StreamBuffer_t * pxBuffer );
  105. static portINLINE size_t uxStreamBufferFrontSpace( const StreamBuffer_t * pxBuffer )
  106. {
  107. /* Distance between uxFront and uxTail
  108. * or the number of items which can still be added to uxFront,
  109. * before hitting on uxTail */
  110. size_t uxFront = pxBuffer->uxFront;
  111. size_t uxTail = pxBuffer->uxTail;
  112. return uxStreamBufferSpace( pxBuffer, uxFront, uxTail );
  113. }
  114. /*-----------------------------------------------------------*/
  115. static portINLINE size_t uxStreamBufferGetSize( const StreamBuffer_t * pxBuffer );
  116. static portINLINE size_t uxStreamBufferGetSize( const StreamBuffer_t * pxBuffer )
  117. {
  118. /* Returns the number of items which can be read from uxTail
  119. * before reaching uxHead */
  120. size_t uxHead = pxBuffer->uxHead;
  121. size_t uxTail = pxBuffer->uxTail;
  122. return uxStreamBufferDistance( pxBuffer, uxTail, uxHead );
  123. }
  124. /*-----------------------------------------------------------*/
  125. static portINLINE size_t uxStreamBufferMidSpace( const StreamBuffer_t * pxBuffer );
  126. static portINLINE size_t uxStreamBufferMidSpace( const StreamBuffer_t * pxBuffer )
  127. {
  128. /* Returns the distance between uxHead and uxMid */
  129. size_t uxHead = pxBuffer->uxHead;
  130. size_t uxMid = pxBuffer->uxMid;
  131. return uxStreamBufferDistance( pxBuffer, uxMid, uxHead );
  132. }
  133. /*-----------------------------------------------------------*/
  134. static portINLINE void vStreamBufferMoveMid( StreamBuffer_t * pxBuffer,
  135. size_t uxCount );
  136. static portINLINE void vStreamBufferMoveMid( StreamBuffer_t * pxBuffer,
  137. size_t uxCount )
  138. {
  139. /* Increment uxMid, but no further than uxHead */
  140. size_t uxSize = uxStreamBufferMidSpace( pxBuffer );
  141. size_t uxMoveCount = uxCount;
  142. if( uxMoveCount > uxSize )
  143. {
  144. uxMoveCount = uxSize;
  145. }
  146. pxBuffer->uxMid += uxMoveCount;
  147. if( pxBuffer->uxMid >= pxBuffer->LENGTH )
  148. {
  149. pxBuffer->uxMid -= pxBuffer->LENGTH;
  150. }
  151. }
  152. /*-----------------------------------------------------------*/
  153. static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t * pxBuffer,
  154. const size_t uxLeft,
  155. const size_t uxRight );
  156. static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t * pxBuffer,
  157. const size_t uxLeft,
  158. const size_t uxRight )
  159. {
  160. BaseType_t xReturn;
  161. size_t uxTail = pxBuffer->uxTail;
  162. /* Returns true if ( uxLeft < uxRight ) */
  163. if( ( ( ( uxLeft < uxTail ) ? 1U : 0U ) ^ ( ( uxRight < uxTail ) ? 1U : 0U ) ) != 0U )
  164. {
  165. if( uxRight < uxTail )
  166. {
  167. xReturn = pdTRUE;
  168. }
  169. else
  170. {
  171. xReturn = pdFALSE;
  172. }
  173. }
  174. else
  175. {
  176. if( uxLeft <= uxRight )
  177. {
  178. xReturn = pdTRUE;
  179. }
  180. else
  181. {
  182. xReturn = pdFALSE;
  183. }
  184. }
  185. return xReturn;
  186. }
  187. /*-----------------------------------------------------------*/
  188. static portINLINE size_t uxStreamBufferGetPtr( StreamBuffer_t * pxBuffer,
  189. uint8_t ** ppucData );
  190. static portINLINE size_t uxStreamBufferGetPtr( StreamBuffer_t * pxBuffer,
  191. uint8_t ** ppucData )
  192. {
  193. size_t uxNextTail = pxBuffer->uxTail;
  194. size_t uxSize = uxStreamBufferGetSize( pxBuffer );
  195. *ppucData = pxBuffer->ucArray + uxNextTail;
  196. return FreeRTOS_min_uint32( uxSize, pxBuffer->LENGTH - uxNextTail );
  197. }
  198. /*
  199. * Add bytes to a stream buffer.
  200. *
  201. * pxBuffer - The buffer to which the bytes will be added.
  202. * uxOffset - If uxOffset > 0, data will be written at an offset from uxHead
  203. * while uxHead will not be moved yet.
  204. * pucData - A pointer to the data to be added.
  205. * uxCount - The number of bytes to add.
  206. */
  207. size_t uxStreamBufferAdd( StreamBuffer_t * pxBuffer,
  208. size_t uxOffset,
  209. const uint8_t * pucData,
  210. size_t uxByteCount );
  211. /*
  212. * Read bytes from a stream buffer.
  213. *
  214. * pxBuffer - The buffer from which the bytes will be read.
  215. * uxOffset - Can be used to read data located at a certain offset from 'uxTail'.
  216. * pucData - A pointer to the buffer into which data will be read.
  217. * uxMaxCount - The number of bytes to read.
  218. * xPeek - If set to pdTRUE the data will remain in the buffer.
  219. */
  220. size_t uxStreamBufferGet( StreamBuffer_t * pxBuffer,
  221. size_t uxOffset,
  222. uint8_t * pucData,
  223. size_t uxMaxCount,
  224. BaseType_t xPeek );
  225. #ifdef __cplusplus
  226. } /* extern "C" */
  227. #endif
  228. #endif /* !defined( FREERTOS_STREAM_BUFFER_H ) */