git subrepo clone https://github.com/libretro/libretro-common.git deps/libretro-common
[pcsx_rearmed.git] / deps / libretro-common / queues / fifo_queue.c
1 /* Copyright  (C) 2010-2020 The RetroArch team
2  *
3  * ---------------------------------------------------------------------------------------
4  * The following license statement only applies to this file (fifo_queue.c).
5  * ---------------------------------------------------------------------------------------
6  *
7  * Permission is hereby granted, free of charge,
8  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <retro_common_api.h>
27 #include <retro_inline.h>
28 #include <boolean.h>
29
30 #include <queues/fifo_queue.h>
31
32 static bool fifo_initialize_internal(fifo_buffer_t *buf, size_t size)
33 {
34    uint8_t *buffer    = (uint8_t*)calloc(1, size + 1);
35
36    if (!buffer)
37       return false;
38
39    buf->buffer        = buffer;
40    buf->size          = size + 1;
41    buf->first         = 0;
42    buf->end           = 0;
43
44    return true;
45 }
46
47 bool fifo_initialize(fifo_buffer_t *buf, size_t size)
48 {
49    if (!buf)
50       return false;
51    return fifo_initialize_internal(buf, size);
52 }
53
54 void fifo_free(fifo_buffer_t *buffer)
55 {
56    if (!buffer)
57       return;
58
59    free(buffer->buffer);
60    free(buffer);
61 }
62
63 bool fifo_deinitialize(fifo_buffer_t *buffer)
64 {
65    if (!buffer)
66       return false;
67
68    if (buffer->buffer)
69       free(buffer->buffer);
70    buffer->buffer = NULL;
71    buffer->size   = 0;
72    buffer->first  = 0;
73    buffer->end    = 0;
74
75    return true;
76 }
77
78 fifo_buffer_t *fifo_new(size_t size)
79 {
80    fifo_buffer_t *buf = (fifo_buffer_t*)malloc(sizeof(*buf));
81
82    if (!buf)
83       return NULL;
84
85    if (!fifo_initialize_internal(buf, size))
86    {
87       free(buf);
88       return NULL;
89    }
90
91    return buf;
92 }
93
94 void fifo_write(fifo_buffer_t *buffer, const void *in_buf, size_t size)
95 {
96    size_t first_write = size;
97    size_t rest_write  = 0;
98
99    if (buffer->end + size > buffer->size)
100    {
101       first_write = buffer->size - buffer->end;
102       rest_write  = size - first_write;
103    }
104
105    memcpy(buffer->buffer + buffer->end, in_buf, first_write);
106    memcpy(buffer->buffer, (const uint8_t*)in_buf + first_write, rest_write);
107
108    buffer->end = (buffer->end + size) % buffer->size;
109 }
110
111 void fifo_read(fifo_buffer_t *buffer, void *in_buf, size_t size)
112 {
113    size_t first_read = size;
114    size_t rest_read  = 0;
115
116    if (buffer->first + size > buffer->size)
117    {
118       first_read = buffer->size - buffer->first;
119       rest_read  = size - first_read;
120    }
121
122    memcpy(in_buf, (const uint8_t*)buffer->buffer + buffer->first, first_read);
123    memcpy((uint8_t*)in_buf + first_read, buffer->buffer, rest_read);
124
125    buffer->first = (buffer->first + size) % buffer->size;
126 }