git subrepo clone https://github.com/libretro/libretro-common.git deps/libretro-common
[pcsx_rearmed.git] / deps / libretro-common / streams / memory_stream.c
1 /* Copyright  (C) 2010-2020 The RetroArch team
2  *
3  * ---------------------------------------------------------------------------------------
4  * The following license statement only applies to this file (memory_stream.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 <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <streams/memory_stream.h>
28
29 /* TODO/FIXME - static globals */
30 static uint8_t* g_buffer      = NULL;
31 static uint64_t g_size         = 0;
32 static uint64_t last_file_size = 0;
33
34 struct memstream
35 {
36    uint64_t size;
37    uint64_t ptr;
38    uint64_t max_ptr;
39    uint8_t *buf;
40    unsigned writing;
41 };
42
43 void memstream_set_buffer(uint8_t *buffer, uint64_t size)
44 {
45    g_buffer = buffer;
46    g_size   = size;
47 }
48
49 uint64_t memstream_get_last_size(void)
50 {
51    return last_file_size;
52 }
53
54 memstream_t *memstream_open(unsigned writing)
55 {
56    memstream_t *stream;
57    if (!g_buffer || !g_size)
58       return NULL;
59
60    stream = (memstream_t*)malloc(sizeof(*stream));
61
62    if (!stream)
63       return NULL;
64
65    stream->buf       = g_buffer;
66    stream->size      = g_size;
67    stream->ptr       = 0;
68    stream->max_ptr   = 0;
69    stream->writing   = writing;
70
71    g_buffer          = NULL;
72    g_size            = 0;
73
74    return stream;
75 }
76
77 void memstream_close(memstream_t *stream)
78 {
79    if (!stream)
80       return;
81
82    last_file_size = stream->writing ? stream->max_ptr : stream->size;
83    free(stream);
84 }
85
86 uint64_t memstream_get_ptr(memstream_t *stream)
87 {
88    return stream->ptr;
89 }
90
91 uint64_t memstream_read(memstream_t *stream, void *data, uint64_t bytes)
92 {
93    uint64_t avail = 0;
94
95    if (!stream)
96       return 0;
97
98    avail               = stream->size - stream->ptr;
99    if (bytes > avail)
100       bytes            = avail;
101
102    memcpy(data, stream->buf + stream->ptr, (size_t)bytes);
103    stream->ptr        += bytes;
104    if (stream->ptr > stream->max_ptr)
105       stream->max_ptr  = stream->ptr;
106    return bytes;
107 }
108
109 uint64_t memstream_write(memstream_t *stream,
110       const void *data, uint64_t bytes)
111 {
112    uint64_t avail = 0;
113
114    if (!stream)
115       return 0;
116
117    avail = stream->size - stream->ptr;
118    if (bytes > avail)
119       bytes = avail;
120
121    memcpy(stream->buf + stream->ptr, data, (size_t)bytes);
122    stream->ptr += bytes;
123    if (stream->ptr > stream->max_ptr)
124       stream->max_ptr = stream->ptr;
125    return bytes;
126 }
127
128 int64_t memstream_seek(memstream_t *stream, int64_t offset, int whence)
129 {
130    uint64_t ptr;
131
132    switch (whence)
133    {
134       case SEEK_SET:
135          ptr = offset;
136          break;
137       case SEEK_CUR:
138          ptr = stream->ptr + offset;
139          break;
140       case SEEK_END:
141          ptr = (stream->writing ? stream->max_ptr : stream->size) + offset;
142          break;
143       default:
144          return -1;
145    }
146
147    if (ptr <= stream->size)
148    {
149       stream->ptr = ptr;
150       return 0;
151    }
152
153    return -1;
154 }
155
156 void memstream_rewind(memstream_t *stream)
157 {
158    memstream_seek(stream, 0L, SEEK_SET);
159 }
160
161 uint64_t memstream_pos(memstream_t *stream)
162 {
163    return stream->ptr;
164 }
165
166 char *memstream_gets(memstream_t *stream, char *buffer, size_t len)
167 {
168    return NULL;
169 }
170
171 int memstream_getc(memstream_t *stream)
172 {
173    int ret = 0;
174    if (stream->ptr >= stream->size)
175       return EOF;
176    ret = stream->buf[stream->ptr++];
177
178    if (stream->ptr > stream->max_ptr)
179       stream->max_ptr = stream->ptr;
180
181    return ret;
182 }
183
184 void memstream_putc(memstream_t *stream, int c)
185 {
186    if (stream->ptr < stream->size)
187       stream->buf[stream->ptr++] = c;
188
189    if (stream->ptr > stream->max_ptr)
190       stream->max_ptr = stream->ptr;
191 }