Blame view

RIOT/core/include/ringbuffer.h 5.05 KB
a752c7ab   elopes   add first test an...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
  /**
   * Ringbuffer header
   *
   * Copyright (C) 2013 Freie Universität Berlin
   * Copyright (C) 2013 INRIA
   *
   * This file is subject to the terms and conditions of the GNU Lesser
   * General Public License v2.1. See the file LICENSE in the top level
   * directory for more details.
   *
   * @ingroup  core_util
   * @{
   * @file
   * @author Kaspar Schleiser <kaspar@schleiser.de>
   * @author René Kijewski <rene.kijewski@fu-berlin.de>
   * @}
   */
  
  #ifndef RINGBUFFER_H
  #define RINGBUFFER_H
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /**
   * @brief     Ringbuffer.
   * @details   Non thread-safe FIFO ringbuffer implementation around a `char` array.
   */
  typedef struct {
      char *buf;          /**< Buffer to operate on. */
      unsigned int size;  /**< Size of buf. */
      unsigned int start; /**< Current read position in the ring buffer. */
      unsigned int avail; /**< Number of elements available for reading. */
  } ringbuffer_t;
  
  /**
   * @def          RINGBUFFER_INIT(BUF)
   * @brief        Initialize a ringbuffer.
   * @details      This macro is meant for static ringbuffers.
   * @param[in]    BUF   Buffer to use for the ringbuffer. The size is deduced through `sizeof (BUF)`.
   * @returns      The static initializer.
   */
  #define RINGBUFFER_INIT(BUF) { (BUF), sizeof (BUF), 0, 0 }
  
  /**
   * @brief        Initialize a ringbuffer.
   * @param[out]   rb        Datum to initialize.
   * @param[in]    buffer    Buffer to use by rb.
   * @param[in]    bufsize   `sizeof (buffer)`
   */
  static inline void ringbuffer_init(ringbuffer_t *__restrict rb, char *buffer, unsigned bufsize)
  {
      rb->buf = buffer;
      rb->size = bufsize;
      rb->start = 0;
      rb->avail = 0;
  }
  
  /**
   * @brief           Add an element to the ringbuffer.
   * @details         If rb is full, then the oldest element gets overwritten.
   *                  Test ringbuffer_full() first if overwriting is not intended.
   * @param[in,out]   rb   Ringbuffer to operate on.
   * @param[in]       c    Element to add.
   * @returns         The element that was dropped, iff the buffer was full.
   *                  -1 iff the buffer was not full.
   */
  int ringbuffer_add_one(ringbuffer_t *__restrict rb, char c);
  
  /**
   * @brief           Add a number of elements to the ringbuffer.
   * @details         Only so many elements are added as fit in the ringbuffer.
   *                  No elements get overwritten.
   *                  If this is not the intended behavior, then use ringbuffer_add_one() in a loop instead.
   * @param[in,out]   rb    Ringbuffer to operate on.
   * @param[in]       buf   Buffer to add elements from.
   * @param[in]       n     Maximum number of elements to add.
   * @returns         Number of elements actually added. 0 if rb is full.
   */
  unsigned ringbuffer_add(ringbuffer_t *__restrict rb, const char *buf, unsigned n);
  
  /**
   * @brief           Peek and remove oldest element from the ringbuffer.
   * @param[in,out]   rb   Ringbuffer to operate on.
   * @returns         The oldest element that was added, or `-1` if rb is empty.
   */
  int ringbuffer_get_one(ringbuffer_t *__restrict rb);
  
  /**
   * @brief           Read and remove a number of elements from the ringbuffer.
   * @param[in,out]   rb    Ringbuffer to operate on.
   * @param[out]      buf   Buffer to write into.
   * @param[in]       n     Read at most n elements.
   * @returns         Number of elements actually read.
   */
  unsigned ringbuffer_get(ringbuffer_t *__restrict rb, char *buf, unsigned n);
  
  /**
   * @brief           Remove a number of elements from the ringbuffer.
   * @param[in,out]   rb    Ringbuffer to operate on.
   * @param[in]       n     Read at most n elements.
   * @returns         Number of elements actually removed.
   */
  unsigned ringbuffer_remove(ringbuffer_t *__restrict rb, unsigned n);
  
  /**
   * @brief           Test if the ringbuffer is empty.
   * @param[in,out]   rb    Ringbuffer to operate on.
   * @returns         0 iff not empty
   */
  static inline int ringbuffer_empty(const ringbuffer_t *__restrict rb)
  {
      return rb->avail == 0;
  }
  
  /**
   * @brief           Test if the ringbuffer is full.
   * @param[in,out]   rb    Ringbuffer to operate on.
   * @returns         0 iff not full
   */
  static inline int ringbuffer_full(const ringbuffer_t *__restrict rb)
  {
      return rb->avail == rb->size;
  }
  
  /**
   * @brief           Return available space in ringbuffer
   * @param[in,out]   rb Ringbuffer to query.
   * @returns         number of available bytes
   */
  static inline unsigned int ringbuffer_get_free(const ringbuffer_t *__restrict rb)
  {
      return rb->size - rb->avail;
  }
  
  /**
   * @brief           Read, but don't remove, the oldest element in the buffer.
   * @param[in]       rb    Ringbuffer to operate on.
   * @returns         Same as ringbuffer_get_one()
   */
  int ringbuffer_peek_one(const ringbuffer_t *__restrict rb);
  
  /**
   * @brief           Read, but don't remove, the a number of element of the buffer.
   * @param[in]       rb    Ringbuffer to operate on.
   * @param[out]      buf   Buffer to write into.
   * @param[in]       n     Read at most n elements.
   * @returns         Same as ringbuffer_get()
   */
  unsigned ringbuffer_peek(const ringbuffer_t *__restrict rb, char *buf, unsigned n);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif /* RINGBUFFER_H */