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