1 /*
2  * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3  */
4 
5 #include "k_api.h"
6 
7 #define RING_BUF_LEN sizeof(size_t)
8 
ringbuf_init(k_ringbuf_t * p_ringbuf,void * buf,size_t len,size_t type,size_t block_size)9 kstat_t ringbuf_init(k_ringbuf_t *p_ringbuf, void *buf, size_t len, size_t type,
10                      size_t block_size)
11 {
12     p_ringbuf->type     = type;
13     p_ringbuf->buf      = buf;
14     p_ringbuf->end      = (uint8_t *)buf + len;
15     p_ringbuf->blk_size = block_size;
16 
17     ringbuf_reset(p_ringbuf);
18 
19     return RHINO_SUCCESS;
20 
21 }
22 
ringbuf_push(k_ringbuf_t * p_ringbuf,void * data,size_t len)23 kstat_t ringbuf_push(k_ringbuf_t *p_ringbuf, void *data, size_t len)
24 {
25     size_t   len_bytes           = 0;
26     size_t   split_len           = 0;
27     uint8_t  c_len[RING_BUF_LEN] = {0};
28 
29     if (p_ringbuf->type == RINGBUF_TYPE_FIX) {
30 
31         if (p_ringbuf->freesize < p_ringbuf->blk_size) {
32             return RHINO_RINGBUF_FULL;
33         }
34 
35         if (p_ringbuf->tail == p_ringbuf->end) {
36             p_ringbuf->tail = p_ringbuf->buf;
37         }
38 
39         memcpy(p_ringbuf->tail, data, p_ringbuf->blk_size);
40         p_ringbuf->tail     += p_ringbuf->blk_size;
41         p_ringbuf->freesize -= p_ringbuf->blk_size;
42     } else {
43         if ((len == 0u) || (len >= (uint32_t) -1)) {
44             return RHINO_INV_PARAM;
45         }
46 
47         len_bytes = RING_BUF_LEN;
48 
49         /* for dynamic length ringbuf */
50         if (p_ringbuf->freesize < (len_bytes + len)) {
51             return RHINO_RINGBUF_FULL;
52         }
53 
54         memcpy(c_len, &len, RING_BUF_LEN);
55 
56         if (p_ringbuf->tail == p_ringbuf->end) {
57             p_ringbuf->tail = p_ringbuf->buf;
58         }
59 
60         /* copy length data to buffer */
61         split_len = p_ringbuf->end - p_ringbuf->tail;
62         if (p_ringbuf->tail >= p_ringbuf->head &&
63             split_len < len_bytes && split_len > 0) {
64             memcpy(p_ringbuf->tail, &c_len[0], split_len);
65             len_bytes -= split_len;
66             p_ringbuf->tail =  p_ringbuf->buf;
67             p_ringbuf->freesize -= split_len;
68         } else {
69             split_len = 0;
70         }
71 
72         if (len_bytes > 0) {
73             memcpy(p_ringbuf->tail, &c_len[split_len], len_bytes);
74             p_ringbuf->freesize -= len_bytes;
75             p_ringbuf->tail += len_bytes;
76         }
77 
78         /* copy data to ringbuf, if break by buffer end, split data and copy to buffer head*/
79         split_len = 0;
80 
81         if (p_ringbuf->tail == p_ringbuf->end) {
82             p_ringbuf->tail = p_ringbuf->buf;
83         }
84 
85         split_len = p_ringbuf->end - p_ringbuf->tail;
86         if (p_ringbuf->tail >= p_ringbuf->head &&
87             split_len < len && split_len > 0) {
88             memcpy(p_ringbuf->tail, data, split_len);
89             data = (uint8_t *)data + split_len;
90             len -= split_len;
91             p_ringbuf->tail =  p_ringbuf->buf;
92             p_ringbuf->freesize -= split_len;
93         }
94 
95         memcpy(p_ringbuf->tail, data, len);
96         p_ringbuf->tail += len;
97         p_ringbuf->freesize -= len;
98     }
99 
100     return RHINO_SUCCESS;
101 }
102 
ringbuf_pop(k_ringbuf_t * p_ringbuf,void * pdata,size_t * plen)103 kstat_t ringbuf_pop(k_ringbuf_t *p_ringbuf, void *pdata, size_t *plen)
104 {
105     size_t   split_len           = 0;
106     uint8_t *data                = pdata;
107     size_t   len                 = 0;
108     uint8_t  c_len[RING_BUF_LEN] = {0};
109     size_t   len_bytes           = 0;
110 
111     if (p_ringbuf->type == RINGBUF_TYPE_FIX) {
112         if (p_ringbuf->head == p_ringbuf->end) {
113             p_ringbuf->head = p_ringbuf->buf;
114         }
115 
116         memcpy(pdata, p_ringbuf->head, p_ringbuf->blk_size);
117         p_ringbuf->head += p_ringbuf->blk_size;
118         p_ringbuf->freesize += p_ringbuf->blk_size;
119 
120         if (plen != NULL) {
121             *plen = p_ringbuf->blk_size;
122         }
123 
124         return RHINO_SUCCESS;
125     } else {
126 
127         len_bytes = RING_BUF_LEN;
128 
129         if (p_ringbuf->head == p_ringbuf->end) {
130             p_ringbuf->head = p_ringbuf->buf;
131         }
132         split_len = p_ringbuf->end - p_ringbuf->head;
133         if (split_len < len_bytes && split_len > 0) {
134             memcpy(&c_len[0], p_ringbuf->head, split_len);
135             p_ringbuf->head      =  p_ringbuf->buf;
136             p_ringbuf->freesize += split_len;
137         } else {
138             split_len = 0;
139         }
140 
141         if (len_bytes - split_len > 0) {
142             memcpy(&c_len[split_len], p_ringbuf->head, (len_bytes - split_len));
143             p_ringbuf->head     += (len_bytes - split_len);
144             p_ringbuf->freesize += (len_bytes - split_len);
145         }
146 
147         memcpy(&len, c_len, RING_BUF_LEN);
148         *plen = len;
149 
150         if (p_ringbuf->head == p_ringbuf->end) {
151             p_ringbuf->head = p_ringbuf->buf;
152         }
153 
154         split_len = p_ringbuf->end - p_ringbuf->head;
155         if (p_ringbuf->head > p_ringbuf->tail && split_len < len) {
156             memcpy(pdata, p_ringbuf->head, split_len);
157             data = (uint8_t *)pdata + split_len;
158             len -= split_len;
159             p_ringbuf->head      = p_ringbuf->buf;
160             p_ringbuf->freesize += split_len;
161         }
162 
163         memcpy(data, p_ringbuf->head, len);
164         p_ringbuf->head     += len;
165         p_ringbuf->freesize += len;
166 
167         return RHINO_SUCCESS;
168     }
169 }
170 
ringbuf_is_full(k_ringbuf_t * p_ringbuf)171 uint8_t ringbuf_is_full(k_ringbuf_t *p_ringbuf)
172 {
173     if (p_ringbuf->type == RINGBUF_TYPE_DYN && p_ringbuf->freesize < (RING_BUF_LEN + 1)) {
174         return 1;
175     }
176 
177     if ((p_ringbuf->type == RINGBUF_TYPE_FIX) &&
178         (p_ringbuf->freesize < p_ringbuf->blk_size)) {
179         return 1;
180     }
181 
182     return 0;
183 }
184 
ringbuf_is_empty(k_ringbuf_t * p_ringbuf)185 uint8_t ringbuf_is_empty(k_ringbuf_t *p_ringbuf)
186 {
187     if (p_ringbuf->freesize == (size_t)(p_ringbuf->end - p_ringbuf->buf)) {
188         return 1;
189     }
190 
191     return 0;
192 }
193 
ringbuf_reset(k_ringbuf_t * p_ringbuf)194 kstat_t ringbuf_reset(k_ringbuf_t *p_ringbuf)
195 {
196     p_ringbuf->head     = p_ringbuf->buf;
197     p_ringbuf->tail     = p_ringbuf->buf;
198     p_ringbuf->freesize = p_ringbuf->end - p_ringbuf->buf;
199 
200     return RHINO_SUCCESS;
201 }
202 
203