• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Chipsea Technologies (Shenzhen) Corp., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  *  ring_buffer.c
17  *
18  */
19 
20 #include <string.h>
21 
22 #include "ring_buffer.h"
23 
24 
25 #ifndef max
26 #define max(a,b)            (((a) > (b)) ? (a) : (b))
27 #endif /* max */
28 
29 #ifndef min
30 #define min(a,b)            (((a) < (b)) ? (a) : (b))
31 #endif /* min */
32 
ring_buffer_init(ring_buffer_t * ring_buffer,uint8_t * storage,uint32_t size)33 int ring_buffer_init(ring_buffer_t *ring_buffer, uint8_t *storage, uint32_t size)
34 {
35     if ((ring_buffer == NULL) || (storage == NULL) || (size == 0)) {
36         return RB_ERR_INVALID_PARAM;
37     }
38 
39     ring_buffer->storage = storage;
40     ring_buffer->size = size;
41     ring_buffer->data_size = 0;
42     ring_buffer->read = 0;
43     ring_buffer->write = 0;
44 
45     return RB_ERR_NONE;
46 }
47 
ring_buffer_deinit(ring_buffer_t * ring_buffer)48 int ring_buffer_deinit(ring_buffer_t *ring_buffer)
49 {
50     if (ring_buffer == NULL) {
51         return RB_ERR_INVALID_PARAM;
52     }
53 
54     ring_buffer->storage = NULL;
55     ring_buffer->size = 0;
56     ring_buffer->data_size = 0;
57     ring_buffer->read = 0;
58     ring_buffer->write = 0;
59 
60     return RB_ERR_NONE;
61 }
62 
ring_buffer_reset(ring_buffer_t * ring_buffer)63 int ring_buffer_reset(ring_buffer_t *ring_buffer)
64 {
65     if (ring_buffer == NULL) {
66         return RB_ERR_INVALID_PARAM;
67     }
68 
69     ring_buffer->data_size = 0;
70     ring_buffer->read = 0;
71     ring_buffer->write = 0;
72 
73     return RB_ERR_NONE;
74 }
75 
ring_buffer_bytes_used(ring_buffer_t * ring_buffer)76 uint32_t ring_buffer_bytes_used(ring_buffer_t *ring_buffer)
77 {
78     return ring_buffer->data_size;
79 }
80 
ring_buffer_empty(ring_buffer_t * ring_buffer)81 int ring_buffer_empty(ring_buffer_t *ring_buffer)
82 {
83     return (ring_buffer->data_size == 0u);
84 }
85 
ring_buffer_bytes_free(ring_buffer_t * ring_buffer)86 uint32_t ring_buffer_bytes_free(ring_buffer_t *ring_buffer)
87 {
88     return (ring_buffer->size - ring_buffer->data_size);
89 }
90 
ring_buffer_write(ring_buffer_t * ring_buffer,uint8_t * data,uint32_t length)91 int ring_buffer_write(ring_buffer_t *ring_buffer, uint8_t *data, uint32_t length)
92 {
93     if ((ring_buffer == NULL) || (ring_buffer->storage == NULL)) {
94         return RB_ERR_INVALID_PARAM;
95     }
96 
97     if (ring_buffer_bytes_free(ring_buffer) < length) {
98         return RB_ERR_NO_ENOUGH_SPACE;
99     }
100 
101     unsigned int bytes_until_end = ring_buffer->size - ring_buffer->write;
102     if (bytes_until_end >= length) {
103         memcpy((void *)&ring_buffer->storage[ring_buffer->write], (void *)data, length);
104         ring_buffer->write += length;
105     } else {
106         // copy first chunk
107         memcpy((void *)&ring_buffer->storage[ring_buffer->write], (void *)data, bytes_until_end);
108         // copy second chunk
109         memcpy((void *)&ring_buffer->storage[0], (void *)(data + bytes_until_end), (length - bytes_until_end));
110         ring_buffer->write = length - bytes_until_end;
111     }
112 
113     if (ring_buffer->write == ring_buffer->size) {
114         ring_buffer->write = 0;
115     }
116 
117     ring_buffer->data_size += length;
118 
119     return RB_ERR_NONE;
120 }
121 
ring_buffer_read(ring_buffer_t * ring_buffer,uint8_t * buffer,uint32_t length)122 int ring_buffer_read(ring_buffer_t *ring_buffer, uint8_t *buffer, uint32_t length)
123 {
124     if ((ring_buffer == NULL) || (ring_buffer->storage == NULL)) {
125         return RB_ERR_INVALID_PARAM;
126     }
127 
128     if (ring_buffer_bytes_used(ring_buffer) < length) {
129         return RB_ERR_NO_ENOUGH_DATA;
130     }
131 
132     unsigned int bytes_until_end = ring_buffer->size - ring_buffer->read;
133 
134     if (buffer != NULL) {
135         if (bytes_until_end >= length) {
136             memcpy((void *)buffer, (void *)&ring_buffer->storage[ring_buffer->read], length);
137             ring_buffer->read += length;
138         } else {
139             // copy first chunk
140             memcpy((void *)buffer, (void *)&ring_buffer->storage[ring_buffer->read], bytes_until_end);
141             // copy second chunk
142             memcpy((void *)(buffer + bytes_until_end), (void *)&ring_buffer->storage[0], (length - bytes_until_end));
143             ring_buffer->read = length - bytes_until_end;
144         }
145     } else {
146         // just modify read index
147         if (bytes_until_end >= length) {
148             ring_buffer->read += length;
149         } else {
150             ring_buffer->read = length - bytes_until_end;
151         }
152     }
153 
154     if (ring_buffer->read == ring_buffer->size) {
155         ring_buffer->read = 0;
156     }
157 
158     ring_buffer->data_size -= length;
159 
160     return RB_ERR_NONE;
161 }
162 
ring_buffer_peek(ring_buffer_t * ring_buffer,uint32_t length,uint8_t ** data1,uint32_t * length1,uint8_t ** data2,uint32_t * length2)163 int ring_buffer_peek(ring_buffer_t *ring_buffer, uint32_t length, uint8_t **data1, uint32_t *length1, uint8_t **data2, uint32_t *length2)
164 {
165     if (ring_buffer_bytes_used(ring_buffer) < length) {
166         return RB_ERR_NO_ENOUGH_DATA;
167     }
168 
169     *data1 = &(ring_buffer->storage[ring_buffer->read]);
170     if((ring_buffer->write > ring_buffer->read) || ((ring_buffer->size - ring_buffer->read) >= length)) {
171         *length1 = length;
172         *data2   = NULL;
173         *length2 = 0;
174         return RB_ERR_NONE;
175     } else {
176         *length1 = ring_buffer->size - ring_buffer->read;
177         *data2   = &(ring_buffer->storage[0]);
178         *length2 = length - *length1;
179         return RB_ERR_NONE;
180     }
181 }
182 
183