MOS Source Code
Loading...
Searching...
No Matches
ring_buffer.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include <algorithm>
4#include <mos/allocator.hpp>
7#include <mos_stdlib.hpp>
8#include <mos_string.hpp>
9
10static u8 ring_buffer_get(u8 *data, ring_buffer_pos_t *pos, size_t index)
11{
12 return data[(pos->head + index) % pos->count];
13}
14
16{
17 if (capacity == 0)
18 return NULL; // forget about it
19
21 if (!rb)
22 return NULL;
23 rb->data = (u8 *) kcalloc<u8>(capacity);
24 if (!rb->data)
25 {
26 delete rb;
27 return NULL;
28 }
29 ring_buffer_pos_init(&rb->pos, capacity);
30 return rb;
31}
32
33ring_buffer_t *ring_buffer_create_at(void *data, size_t capacity)
34{
35 if (capacity == 0)
36 return NULL; // forget about it
37
39 if (!rb)
40 return NULL;
41 rb->data = (u8 *) data;
42 ring_buffer_pos_init(&rb->pos, capacity);
43 return rb;
44}
45
46void ring_buffer_pos_init(ring_buffer_pos_t *pos, size_t capacity)
47{
48 pos->capacity = capacity;
49 pos->count = 0;
50 pos->head = 0;
51 pos->next_pos = 0;
52}
53
55{
56 kfree(buffer->data);
57 delete buffer;
58}
59
60bool ring_buffer_resize(ring_buffer_t *buffer, size_t new_capacity)
61{
62 if (new_capacity < buffer->pos.count)
63 return false;
64 void *new_data = kcalloc<char>(new_capacity);
65 if (!new_data)
66 return false;
67 size_t i = 0;
68 while (i < buffer->pos.count)
69 {
70 ((char *) new_data)[i] = ring_buffer_get(buffer->data, &buffer->pos, i);
71 i++;
72 }
73
74 kfree(buffer->data);
75 buffer->data = (u8 *) new_data;
76 buffer->pos.capacity = new_capacity;
77 buffer->pos.head = 0;
78 buffer->pos.next_pos = buffer->pos.count;
79 return true;
80}
81
82size_t ring_buffer_pos_push_back(u8 *data, ring_buffer_pos_t *pos, const u8 *target, size_t size)
83{
84 if (pos->count + size > pos->capacity)
85 size = pos->capacity - pos->count;
86
87 size_t first_part_i = pos->next_pos;
88 size_t first_part_size = std::min(size, pos->capacity - pos->next_pos);
89 size_t second_part = size - first_part_size;
90 memcpy(data + first_part_i, target, first_part_size);
91 memcpy(data, target + first_part_size, second_part);
92 pos->next_pos = (pos->next_pos + size) % pos->capacity;
93 pos->count += size;
94 return size;
95}
96
97size_t ring_buffer_pos_pop_back(u8 *data, ring_buffer_pos_t *pos, u8 *target, size_t size)
98{
99 if (size > pos->count)
100 size = pos->count;
101
102 size_t first_part_i = (pos->capacity + pos->next_pos - size) % pos->capacity;
103 size_t first_part_size = std::min(size, pos->capacity - first_part_i);
104
105 size_t second_part_i = 0;
106 size_t second_part_size = size - first_part_size;
107
108 memcpy(target, data + first_part_i, first_part_size);
109 memcpy(target + first_part_size, data + second_part_i, second_part_size);
110
111 pos->next_pos = (pos->capacity + pos->next_pos - size) % pos->capacity;
112 pos->count -= size;
113
114 return size;
115}
116
117size_t ring_buffer_pos_push_front(u8 *data, ring_buffer_pos_t *pos, const u8 *target, size_t size)
118{
119 if (pos->count + size > pos->capacity)
120 return 0;
121
122 size_t first_part_i = (pos->capacity + pos->head - size) % pos->capacity;
123 size_t first_part_size = std::min(size, pos->capacity - first_part_i);
124
125 size_t second_part_i = 0;
126 size_t second_part_size = size - first_part_size;
127
128 memcpy(data + first_part_i, target, first_part_size);
129 memcpy(data + second_part_i, target + first_part_size, second_part_size);
130
131 pos->head = (pos->capacity + pos->head - size) % pos->capacity;
132 pos->count += size;
133 return size;
134}
135
136size_t ring_buffer_pos_pop_front(u8 *data, ring_buffer_pos_t *pos, u8 *target, size_t size)
137{
138 if (size > pos->count)
139 size = pos->count;
140
141 size_t first_part_i = pos->head;
142 size_t first_part_size = std::min(size, pos->capacity - first_part_i);
143
144 size_t second_part_i = 0;
145 size_t second_part_size = size - first_part_size;
146
147 memcpy(target, data + first_part_i, first_part_size);
148 memcpy(target + first_part_size, data + second_part_i, second_part_size);
149
150 pos->head = (pos->head + size) % pos->capacity;
151 pos->count -= size;
152 return size;
153}
void ring_buffer_destroy(ring_buffer_t *buffer)
ring_buffer_t * ring_buffer_create_at(void *data, size_t capacity)
size_t ring_buffer_pos_pop_back(u8 *data, ring_buffer_pos_t *pos, u8 *target, size_t size)
size_t ring_buffer_pos_pop_front(u8 *data, ring_buffer_pos_t *pos, u8 *target, size_t size)
size_t ring_buffer_pos_push_front(u8 *data, ring_buffer_pos_t *pos, const u8 *target, size_t size)
bool ring_buffer_resize(ring_buffer_t *buffer, size_t new_capacity)
void ring_buffer_pos_init(ring_buffer_pos_t *pos, size_t capacity)
ring_buffer_t * ring_buffer_create(size_t capacity)
size_t ring_buffer_pos_push_back(u8 *data, ring_buffer_pos_t *pos, const u8 *target, size_t size)
T * create(Args &&...args)
Definition allocator.hpp:10
static void * memcpy(void *s1, const void *s2, size_t n)
Definition pb_syshdr.h:90
#define NULL
Definition pb_syshdr.h:46
static u8 ring_buffer_get(u8 *data, ring_buffer_pos_t *pos, size_t index)
size_t size
Definition slab.cpp:34
ring_buffer_pos_t pos
static char buffer[2048]
unsigned char u8
Definition types.h:15