1 /* Copyright (C) 2010-2020 The RetroArch team
3 * ---------------------------------------------------------------------------------------
4 * The following license statement only applies to this file (nbio_stdio.c).
5 * ---------------------------------------------------------------------------------------
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:
13 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
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.
29 #include <file/nbio.h>
30 #include <encodings/utf.h>
32 /* Assume W-functions do not work below Win2K and Xbox platforms */
33 #if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500 || defined(_XBOX)
42 #if defined(_MSC_VER) && _MSC_VER >= 1400
43 #define ATLEAST_VC2005
47 #if (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE - 0) >= 200112) || (defined(__POSIX_VISIBLE) && __POSIX_VISIBLE >= 200112) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112) || __USE_LARGEFILE || (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64)
48 #ifndef HAVE_64BIT_OFFSETS
49 #define HAVE_64BIT_OFFSETS
61 * NBIO_READ, NBIO_WRITE - obvious
62 * -1 - currently doing nothing
63 * -2 - the pointer was reallocated since the last operation
69 #if !defined(_WIN32) || defined(LEGACY_WIN32)
70 static const char *stdio_modes[] = { "rb", "wb", "r+b", "rb", "wb", "r+b" };
72 static const wchar_t *stdio_modes[] = { L"rb", L"wb", L"r+b", L"rb", L"wb", L"r+b" };
75 static int64_t fseek_wrap(FILE *f, int64_t offset, int origin)
78 /* VC2005 and up have a special 64-bit fseek */
79 return _fseeki64(f, offset, origin);
80 #elif defined(HAVE_64BIT_OFFSETS)
81 return fseeko(f, (off_t)offset, origin);
83 return fseek(f, (long)offset, origin);
87 static int64_t ftell_wrap(FILE *f)
90 /* VC2005 and up have a special 64-bit ftell */
92 #elif defined(HAVE_64BIT_OFFSETS)
99 static void *nbio_stdio_open(const char * filename, unsigned mode)
102 struct nbio_stdio_t* handle = NULL;
104 #if !defined(_WIN32) || defined(LEGACY_WIN32)
105 FILE* f = fopen(filename, stdio_modes[mode]);
107 wchar_t *filename_wide = utf8_to_utf16_string_alloc(filename);
108 FILE* f = _wfopen(filename_wide, stdio_modes[mode]);
116 handle = (struct nbio_stdio_t*)malloc(sizeof(struct nbio_stdio_t));
129 fseek_wrap(handle->f, 0, SEEK_END);
130 len = ftell_wrap(handle->f);
137 /* hit the aligned-buffer fast path on Wii U */
139 buf = memalign(0x40, (size_t)len);
142 buf = malloc((size_t)len);
150 handle->progress = handle->len;
162 static void nbio_stdio_begin_read(void *data)
164 struct nbio_stdio_t *handle = (struct nbio_stdio_t*)data;
171 fseek_wrap(handle->f, 0, SEEK_SET);
173 handle->op = NBIO_READ;
174 handle->progress = 0;
177 static void nbio_stdio_begin_write(void *data)
179 struct nbio_stdio_t *handle = (struct nbio_stdio_t*)data;
186 fseek_wrap(handle->f, 0, SEEK_SET);
187 handle->op = NBIO_WRITE;
188 handle->progress = 0;
191 static bool nbio_stdio_iterate(void *data)
193 size_t amount = 65536;
194 struct nbio_stdio_t *handle = (struct nbio_stdio_t*)data;
199 if (amount > handle->len - handle->progress)
200 amount = handle->len - handle->progress;
205 if (handle->mode == BIO_READ)
207 amount = handle->len;
208 fread((char*)handle->data, 1, amount, handle->f);
211 fread((char*)handle->data + handle->progress, 1, amount, handle->f);
214 if (handle->mode == BIO_WRITE)
217 amount = handle->len;
218 written = fwrite((char*)handle->data, 1, amount, handle->f);
219 if (written != amount)
223 fwrite((char*)handle->data + handle->progress, 1, amount, handle->f);
227 handle->progress += amount;
229 if (handle->progress == handle->len)
231 return (handle->op < 0);
234 static void nbio_stdio_resize(void *data, size_t len)
236 void *new_data = NULL;
237 struct nbio_stdio_t *handle = (struct nbio_stdio_t*)data;
243 if (len < handle->len)
247 handle->progress = len;
250 new_data = realloc(handle->data, handle->len);
253 handle->data = new_data;
256 static void *nbio_stdio_get_ptr(void *data, size_t* len)
258 struct nbio_stdio_t *handle = (struct nbio_stdio_t*)data;
263 if (handle->op == -1)
268 static void nbio_stdio_cancel(void *data)
270 struct nbio_stdio_t *handle = (struct nbio_stdio_t*)data;
275 handle->progress = handle->len;
278 static void nbio_stdio_free(void *data)
280 struct nbio_stdio_t *handle = (struct nbio_stdio_t*)data;
293 nbio_intf_t nbio_stdio = {
295 nbio_stdio_begin_read,
296 nbio_stdio_begin_write,