update libretro-common
This commit is contained in:
parent
3685c6e1f6
commit
b0f4989230
|
@ -216,9 +216,6 @@ static int file_archive_get_file_list_cb(
|
|||
(void)csize;
|
||||
(void)size;
|
||||
(void)checksum;
|
||||
(void)valid_exts;
|
||||
(void)file_ext;
|
||||
(void)ext_list;
|
||||
|
||||
memset(&attr, 0, sizeof(attr));
|
||||
|
||||
|
@ -538,10 +535,8 @@ static bool file_archive_parse_file(const char *file, const char *valid_exts,
|
|||
|
||||
for (;;)
|
||||
{
|
||||
int ret = file_archive_parse_file_iterate(&state, &returnerr, file,
|
||||
valid_exts, file_cb, userdata);
|
||||
|
||||
if (ret != 0)
|
||||
if (file_archive_parse_file_iterate(&state, &returnerr, file,
|
||||
valid_exts, file_cb, userdata) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -656,7 +651,7 @@ bool file_archive_perform_mode(const char *path, const char *valid_exts,
|
|||
{
|
||||
case ZLIB_MODE_UNCOMPRESSED:
|
||||
if (!filestream_write_file(path, cdata, size))
|
||||
return false;
|
||||
goto error;
|
||||
break;
|
||||
|
||||
case ZLIB_MODE_DEFLATE:
|
||||
|
@ -667,7 +662,7 @@ bool file_archive_perform_mode(const char *path, const char *valid_exts,
|
|||
|
||||
if (!handle.backend->stream_decompress_data_to_file_init(&handle,
|
||||
cdata, csize, size))
|
||||
return false;
|
||||
goto error;
|
||||
|
||||
do{
|
||||
ret = handle.backend->stream_decompress_data_to_file_iterate(
|
||||
|
@ -677,14 +672,17 @@ bool file_archive_perform_mode(const char *path, const char *valid_exts,
|
|||
if (!file_archive_decompress_data_to_file(&handle,
|
||||
ret, path, valid_exts,
|
||||
cdata, csize, size, crc32))
|
||||
return false;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
return false;
|
||||
}
|
||||
|
||||
const struct file_archive_file_backend *file_archive_get_default_file_backend(void)
|
||||
|
|
|
@ -167,7 +167,7 @@ static int zlib_stream_decompress_data_to_file_iterate(void *data)
|
|||
z_stream *stream = (z_stream*)data;
|
||||
|
||||
if (!stream)
|
||||
return -1;
|
||||
goto error;
|
||||
|
||||
zstatus = inflate(stream, Z_NO_FLUSH);
|
||||
|
||||
|
@ -175,9 +175,12 @@ static int zlib_stream_decompress_data_to_file_iterate(void *data)
|
|||
return 1;
|
||||
|
||||
if (zstatus != Z_OK && zstatus != Z_BUF_ERROR)
|
||||
return -1;
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void zlib_stream_compress_init(void *data, int level)
|
||||
|
|
|
@ -421,6 +421,15 @@ void rglLinkProgram(GLuint program)
|
|||
glLinkProgram(program);
|
||||
}
|
||||
|
||||
void rglFramebufferTexture(GLenum target, GLenum attachment,
|
||||
GLuint texture, GLint level)
|
||||
{
|
||||
#if defined(HAVE_OPENGLES) && !defined(HAVE_OPENGLES32)
|
||||
#else
|
||||
glFramebufferTexture(target, attachment, texture, level);
|
||||
#endif
|
||||
}
|
||||
|
||||
void rglFramebufferTexture2D(GLenum target, GLenum attachment,
|
||||
GLenum textarget, GLuint texture, GLint level)
|
||||
{
|
||||
|
@ -446,7 +455,7 @@ void rglFramebufferRenderbuffer(GLenum target, GLenum attachment,
|
|||
glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
|
||||
}
|
||||
|
||||
void rglDeleteFramebuffers(GLsizei n, GLuint *framebuffers)
|
||||
void rglDeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
|
||||
{
|
||||
glDeleteFramebuffers(n, framebuffers);
|
||||
}
|
||||
|
@ -703,6 +712,12 @@ void rglUniform4fv(GLint location, GLsizei count, const GLfloat *value)
|
|||
glUniform4fv(location, count, value);
|
||||
}
|
||||
|
||||
void rglTexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height)
|
||||
{
|
||||
glTexStorage2D(target, levels, internalFormat, width, height);
|
||||
}
|
||||
|
||||
void rglPolygonOffset(GLfloat factor, GLfloat units)
|
||||
{
|
||||
glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL);
|
||||
|
@ -712,6 +727,41 @@ void rglPolygonOffset(GLfloat factor, GLfloat units)
|
|||
gl_state.polygonoffset.units = units;
|
||||
}
|
||||
|
||||
void rglDrawBuffers(GLsizei n, const GLenum *bufs)
|
||||
{
|
||||
#if defined(HAVE_OPENGLES) && !defined(HAVE_OPENGLES3) && !defined(HAVE_OPENGLES31)
|
||||
#else
|
||||
glDrawBuffers(n, bufs);
|
||||
#endif
|
||||
}
|
||||
|
||||
void rglBlendEquation(GLenum mode)
|
||||
{
|
||||
glBlendEquation(mode);
|
||||
}
|
||||
|
||||
void rglBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
|
||||
{
|
||||
glBlendColor(red, green, blue, alpha);
|
||||
}
|
||||
|
||||
|
||||
void rglBindVertexArray(GLuint array)
|
||||
{
|
||||
#if defined(HAVE_OPENGLES) && !defined(HAVE_OPENGLES3) && !defined(HAVE_OPENGLES31)
|
||||
#else
|
||||
glBindVertexArray(array);
|
||||
#endif
|
||||
}
|
||||
|
||||
void rglGenVertexArrays(GLsizei n, GLuint *arrays)
|
||||
{
|
||||
#if defined(HAVE_OPENGLES) && !defined(HAVE_OPENGLES3) && !defined(HAVE_OPENGLES31)
|
||||
#else
|
||||
glGenVertexArrays(n, arrays);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* GLSM-side */
|
||||
|
||||
static void glsm_state_setup(void)
|
||||
|
|
|
@ -41,6 +41,7 @@ extern "C" {
|
|||
#define glCompressedTexImage2D rglCompressedTexImage2D
|
||||
#define glBindTexture rglBindTexture
|
||||
#define glActiveTexture rglActiveTexture
|
||||
#define glFramebufferTexture rglFramebufferTexture
|
||||
#define glFramebufferTexture2D rglFramebufferTexture2D
|
||||
#define glFramebufferRenderbuffer rglFramebufferRenderbuffer
|
||||
#define glDeleteFramebuffers rglDeleteFramebuffers
|
||||
|
@ -112,22 +113,35 @@ extern "C" {
|
|||
#define glReadBuffer rglReadBuffer
|
||||
#define glUniformMatrix4fv rglUniformMatrix4fv
|
||||
#define glGetAttribLocation rglGetAttribLocation
|
||||
#define glTexStorage2D rglTexStorage2D
|
||||
#define glDrawBuffers rglDrawBuffers
|
||||
#define glGenVertexArrays rglGenVertexArrays
|
||||
#define glBindVertexArray rglBindVertexArray
|
||||
#define glBlendEquation rglBlendEquation
|
||||
#define glBlendColor rglBlendColor
|
||||
|
||||
void rglBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
void rglBlendEquation(GLenum mode);
|
||||
void rglGenVertexArrays(GLsizei n, GLuint *arrays);
|
||||
void rglReadBuffer(GLenum mode);
|
||||
void rglPixelStorei(GLenum pname, GLint param);
|
||||
void rglTexCoord2f(GLfloat s, GLfloat t);
|
||||
void rglDrawElements(GLenum mode, GLsizei count, GLenum type,
|
||||
const GLvoid * indices);
|
||||
void rglTexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height);
|
||||
void rglCompressedTexImage2D(GLenum target, GLint level,
|
||||
GLenum internalformat, GLsizei width, GLsizei height,
|
||||
GLint border, GLsizei imageSize, const GLvoid *data);
|
||||
void glBindTexture(GLenum target, GLuint texture);
|
||||
void glActiveTexture(GLenum texture);
|
||||
void rglFramebufferTexture(GLenum target, GLenum attachment,
|
||||
GLuint texture, GLint level);
|
||||
void rglFramebufferTexture2D(GLenum target, GLenum attachment,
|
||||
GLenum textarget, GLuint texture, GLint level);
|
||||
void rglFramebufferRenderbuffer(GLenum target, GLenum attachment,
|
||||
GLenum renderbuffertarget, GLuint renderbuffer);
|
||||
void rglDeleteFramebuffers(GLsizei n, GLuint *framebuffers);
|
||||
void rglDeleteFramebuffers(GLsizei n, const GLuint *framebuffers);
|
||||
void rglRenderbufferStorage(GLenum target, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height);
|
||||
void rglDeleteTextures(GLsizei n, const GLuint *textures);
|
||||
|
@ -214,6 +228,8 @@ void rglDetachShader(GLuint program, GLuint shader);
|
|||
void rglUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose,
|
||||
const GLfloat *value);
|
||||
GLint rglGetAttribLocation(GLuint program, const GLchar *name);
|
||||
void rglDrawBuffers(GLsizei n, const GLenum *bufs);
|
||||
void rglBindVertexArray(GLuint array);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -65,6 +65,11 @@ bool file_list_append(file_list_t *userdata, const char *path,
|
|||
const char *label, unsigned type, size_t current_directory_ptr,
|
||||
size_t entry_index);
|
||||
|
||||
bool file_list_prepend(file_list_t *list,
|
||||
const char *path, const char *label,
|
||||
unsigned type, size_t directory_ptr,
|
||||
size_t entry_idx);
|
||||
|
||||
void file_list_pop(file_list_t *list, size_t *directory_ptr);
|
||||
|
||||
void file_list_clear(file_list_t *list);
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
#ifndef __LIBRETRO_SDK_SEMAPHORE_H
|
||||
#define __LIBRETRO_SDK_SEMAPHORE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct ssem ssem_t;
|
||||
|
||||
/**
|
||||
|
@ -37,8 +41,14 @@ ssem_t *ssem_new(int value);
|
|||
|
||||
void ssem_free(ssem_t *semaphore);
|
||||
|
||||
int ssem_get(ssem_t *semaphore);
|
||||
|
||||
void ssem_wait(ssem_t *semaphore);
|
||||
|
||||
void ssem_signal(ssem_t *semaphore);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LIBRETRO_SDK_SEMAPHORE_H */
|
||||
|
|
|
@ -66,6 +66,8 @@ int filestream_read_file(const char *path, void **buf, ssize_t *len);
|
|||
|
||||
bool filestream_write_file(const char *path, const void *data, ssize_t size);
|
||||
|
||||
int filestream_putc(RFILE *stream, int c);
|
||||
|
||||
int filestream_get_fd(RFILE *stream);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/* Copyright (C) 2010-2015 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (interface_stream.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _LIBRETRO_SDK_INTERFACE_STREAM_H
|
||||
#define _LIBRETRO_SDK_INTERFACE_STREAM_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
enum intfstream_type
|
||||
{
|
||||
INTFSTREAM_FILE = 0,
|
||||
INTFSTREAM_MEMORY
|
||||
};
|
||||
|
||||
typedef struct intfstream_internal intfstream_internal_t;
|
||||
|
||||
typedef struct intfstream intfstream_t;
|
||||
|
||||
typedef struct intfstream_info
|
||||
{
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
} buf;
|
||||
bool writable;
|
||||
} memory;
|
||||
enum intfstream_type type;
|
||||
} intfstream_info_t;
|
||||
|
||||
void *intfstream_init(intfstream_info_t *info);
|
||||
|
||||
bool intfstream_resize(intfstream_internal_t *intf,
|
||||
intfstream_info_t *info);
|
||||
|
||||
bool intfstream_open(intfstream_internal_t *intf,
|
||||
const char *path, unsigned mode, ssize_t len);
|
||||
|
||||
ssize_t intfstream_read(intfstream_internal_t *intf,
|
||||
void *s, size_t len);
|
||||
|
||||
ssize_t intfstream_write(intfstream_internal_t *intf,
|
||||
const void *s, size_t len);
|
||||
|
||||
char *intfstream_gets(intfstream_internal_t *intf,
|
||||
char *buffer, size_t len);
|
||||
|
||||
int intfstream_getc(intfstream_internal_t *intf);
|
||||
|
||||
int intfstream_seek(intfstream_internal_t *intf,
|
||||
int offset, int whence);
|
||||
|
||||
void intfstream_rewind(intfstream_internal_t *intf);
|
||||
|
||||
int intfstream_tell(intfstream_internal_t *intf);
|
||||
|
||||
void intfstream_putc(intfstream_internal_t *intf, int c);
|
||||
|
||||
int intfstream_close(intfstream_internal_t *intf);
|
||||
|
||||
#endif
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
typedef struct memstream memstream_t;
|
||||
|
||||
memstream_t *memstream_open(void);
|
||||
memstream_t *memstream_open(unsigned writing);
|
||||
|
||||
void memstream_close(memstream_t *stream);
|
||||
|
||||
|
@ -38,10 +38,14 @@ size_t memstream_write(memstream_t *stream, const void *data, size_t bytes);
|
|||
|
||||
int memstream_getc(memstream_t *stream);
|
||||
|
||||
void memstream_putc(memstream_t *stream, int c);
|
||||
|
||||
char *memstream_gets(memstream_t *stream, char *buffer, size_t len);
|
||||
|
||||
size_t memstream_pos(memstream_t *stream);
|
||||
|
||||
void memstream_rewind(memstream_t *stream);
|
||||
|
||||
int memstream_seek(memstream_t *stream, int offset, int whence);
|
||||
|
||||
void memstream_set_buffer(uint8_t *buffer, size_t size);
|
||||
|
|
|
@ -24,7 +24,7 @@ static void (*co_swap)(cothread_t, cothread_t) = 0;
|
|||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
//ABI: Win64
|
||||
/* ABI: Win64 */
|
||||
static unsigned char co_swap_function[] = {
|
||||
0x48, 0x89, 0x22, /* mov [rdx],rsp */
|
||||
0x48, 0x8b, 0x21, /* mov rsp,[rcx] */
|
||||
|
@ -81,7 +81,7 @@ void co_init(void)
|
|||
sizeof(co_swap_function), PAGE_EXECUTE_READWRITE, &old_privileges);
|
||||
}
|
||||
#else
|
||||
//ABI: SystemV
|
||||
/* ABI: SystemV */
|
||||
#ifndef CO_USE_INLINE_ASM
|
||||
static unsigned char co_swap_function[] = {
|
||||
0x48, 0x89, 0x26, /* mov [rsi],rsp */
|
||||
|
|
|
@ -59,6 +59,49 @@ static bool file_list_capacity(file_list_t *list, size_t cap)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool file_list_prepend(file_list_t *list,
|
||||
const char *path, const char *label,
|
||||
unsigned type, size_t directory_ptr,
|
||||
size_t entry_idx)
|
||||
{
|
||||
unsigned i;
|
||||
if (list->size >= list->capacity &&
|
||||
!file_list_capacity(list, list->capacity * 2 + 1))
|
||||
return false;
|
||||
|
||||
list->size++;
|
||||
|
||||
for (i = list->size -1; i > 0; i--)
|
||||
{
|
||||
struct item_file *copy = calloc(1, sizeof(struct item_file));
|
||||
|
||||
memcpy(copy, &list->list[i-1], sizeof(struct item_file));
|
||||
|
||||
memcpy(&list->list[i-1], &list->list[i], sizeof(struct item_file));
|
||||
memcpy(&list->list[i], copy, sizeof(struct item_file));
|
||||
|
||||
free(copy);
|
||||
}
|
||||
|
||||
memset(&list->list[0], 0, sizeof(file_list_t));
|
||||
|
||||
list->list[0].label = NULL;
|
||||
list->list[0].path = NULL;
|
||||
list->list[0].alt = NULL;
|
||||
list->list[0].userdata = NULL;
|
||||
list->list[0].actiondata = NULL;
|
||||
list->list[0].type = type;
|
||||
list->list[0].directory_ptr = directory_ptr;
|
||||
list->list[0].entry_idx = entry_idx;
|
||||
|
||||
if (label)
|
||||
list->list[0].label = strdup(label);
|
||||
if (path)
|
||||
list->list[0].path = strdup(path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool file_list_append(file_list_t *list,
|
||||
const char *path, const char *label,
|
||||
unsigned type, size_t directory_ptr,
|
||||
|
|
|
@ -175,12 +175,9 @@ void msg_queue_clear(msg_queue_t *queue)
|
|||
**/
|
||||
const char *msg_queue_pull(msg_queue_t *queue)
|
||||
{
|
||||
struct queue_elem *front = NULL, *last = NULL,
|
||||
*parent = NULL, *child = NULL;
|
||||
struct queue_elem *front = NULL, *last = NULL;
|
||||
size_t tmp_ptr = 1;
|
||||
|
||||
(void)parent;
|
||||
(void)child;
|
||||
(void)tmp_ptr;
|
||||
|
||||
/* Nothing in queue. */
|
||||
|
@ -203,10 +200,12 @@ const char *msg_queue_pull(msg_queue_t *queue)
|
|||
|
||||
for (;;)
|
||||
{
|
||||
size_t switch_index = tmp_ptr;
|
||||
bool left = (tmp_ptr * 2 <= queue->ptr)
|
||||
struct queue_elem *parent = NULL;
|
||||
struct queue_elem *child = NULL;
|
||||
size_t switch_index = tmp_ptr;
|
||||
bool left = (tmp_ptr * 2 <= queue->ptr)
|
||||
&& (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2]);
|
||||
bool right = (tmp_ptr * 2 + 1 <= queue->ptr)
|
||||
bool right = (tmp_ptr * 2 + 1 <= queue->ptr)
|
||||
&& (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2 + 1]);
|
||||
|
||||
if (!left && !right)
|
||||
|
@ -227,9 +226,9 @@ const char *msg_queue_pull(msg_queue_t *queue)
|
|||
|
||||
parent = (struct queue_elem*)queue->elems[tmp_ptr];
|
||||
child = (struct queue_elem*)queue->elems[switch_index];
|
||||
queue->elems[tmp_ptr] = child;
|
||||
queue->elems[tmp_ptr] = child;
|
||||
queue->elems[switch_index] = parent;
|
||||
tmp_ptr = switch_index;
|
||||
tmp_ptr = switch_index;
|
||||
}
|
||||
|
||||
return queue->tmp_msg;
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef __unix__
|
||||
#define _POSIX_C_SOURCE 199309
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rthreads/rthreads.h>
|
||||
|
@ -73,6 +77,21 @@ void ssem_free(ssem_t *semaphore)
|
|||
free((void*)semaphore);
|
||||
}
|
||||
|
||||
int ssem_get(ssem_t *semaphore)
|
||||
{
|
||||
int val = 0;
|
||||
if (!semaphore)
|
||||
return 0;
|
||||
|
||||
slock_lock(semaphore->mutex);
|
||||
|
||||
val = semaphore->value;
|
||||
|
||||
slock_unlock(semaphore->mutex);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void ssem_wait(ssem_t *semaphore)
|
||||
{
|
||||
if (!semaphore)
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef __unix__
|
||||
#define _POSIX_C_SOURCE 199309
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
|
|
@ -66,10 +66,6 @@
|
|||
#include <streams/file_stream.h>
|
||||
#include <memmap.h>
|
||||
|
||||
#if 1
|
||||
#define HAVE_BUFFERED_IO 1
|
||||
#endif
|
||||
|
||||
struct RFILE
|
||||
{
|
||||
unsigned hints;
|
||||
|
@ -78,6 +74,9 @@ struct RFILE
|
|||
#elif defined(__CELLOS_LV2__)
|
||||
int fd;
|
||||
#else
|
||||
|
||||
#define HAVE_BUFFERED_IO 1
|
||||
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
FILE *fp;
|
||||
#endif
|
||||
|
@ -94,28 +93,25 @@ int filestream_get_fd(RFILE *stream)
|
|||
{
|
||||
if (!stream)
|
||||
return -1;
|
||||
#if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__)
|
||||
return stream->fd;
|
||||
#else
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
return fileno(stream->fp);
|
||||
#endif
|
||||
return stream->fd;
|
||||
#endif
|
||||
}
|
||||
|
||||
RFILE *filestream_open(const char *path, unsigned mode, ssize_t len)
|
||||
{
|
||||
int flags = 0;
|
||||
int mode_int = 0;
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
const char *mode_str = NULL;
|
||||
#endif
|
||||
RFILE *stream = (RFILE*)calloc(1, sizeof(*stream));
|
||||
|
||||
if (!stream)
|
||||
return NULL;
|
||||
|
||||
(void)mode_str;
|
||||
(void)mode_int;
|
||||
(void)flags;
|
||||
|
||||
|
@ -220,7 +216,8 @@ RFILE *filestream_open(const char *path, unsigned mode, ssize_t len)
|
|||
|
||||
filestream_rewind(stream);
|
||||
|
||||
stream->mapped = (uint8_t*)mmap((void*)0, stream->mapsize, PROT_READ, MAP_SHARED, stream->fd, 0);
|
||||
stream->mapped = (uint8_t*)mmap((void*)0,
|
||||
stream->mapsize, PROT_READ, MAP_SHARED, stream->fd, 0);
|
||||
|
||||
if (stream->mapped == MAP_FAILED)
|
||||
stream->hints &= ~RFILE_HINT_MMAP;
|
||||
|
@ -243,98 +240,103 @@ error:
|
|||
|
||||
ssize_t filestream_seek(RFILE *stream, ssize_t offset, int whence)
|
||||
{
|
||||
int ret = 0;
|
||||
#if defined(__CELLOS_LV2__)
|
||||
uint64_t pos = 0;
|
||||
#endif
|
||||
if (!stream)
|
||||
return -1;
|
||||
|
||||
(void)ret;
|
||||
goto error;
|
||||
|
||||
#if defined(VITA) || defined(PSP)
|
||||
ret = sceIoLseek(stream->fd, (SceOff)offset, whence);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
if (sceIoLseek(stream->fd, (SceOff)offset, whence) == -1)
|
||||
goto error;
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
uint64_t pos = 0;
|
||||
if (cellFsLseek(stream->fd, offset, whence, &pos) != CELL_FS_SUCCEEDED)
|
||||
return -1;
|
||||
return 0;
|
||||
goto error;
|
||||
#else
|
||||
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
return fseek(stream->fp, (long)offset, whence);
|
||||
else
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
/* Need to check stream->mapped because this function is
|
||||
* called in filestream_open() */
|
||||
if (stream->mapped && stream->hints & RFILE_HINT_MMAP)
|
||||
/* Need to check stream->mapped because this function is
|
||||
* called in filestream_open() */
|
||||
if (stream->mapped && stream->hints & RFILE_HINT_MMAP)
|
||||
{
|
||||
/* fseek() returns error on under/overflow but allows cursor > EOF for
|
||||
read-only file descriptors. */
|
||||
switch (whence)
|
||||
{
|
||||
/* fseek() returns error on under/overflow but allows cursor > EOF for
|
||||
read-only file descriptors. */
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
if (offset < 0)
|
||||
return -1;
|
||||
case SEEK_SET:
|
||||
if (offset < 0)
|
||||
goto error;
|
||||
|
||||
stream->mappos = offset;
|
||||
break;
|
||||
stream->mappos = offset;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
if ((offset < 0 && stream->mappos + offset > stream->mappos) ||
|
||||
(offset > 0 && stream->mappos + offset < stream->mappos))
|
||||
return -1;
|
||||
case SEEK_CUR:
|
||||
if ((offset < 0 && stream->mappos + offset > stream->mappos) ||
|
||||
(offset > 0 && stream->mappos + offset < stream->mappos))
|
||||
goto error;
|
||||
|
||||
stream->mappos += offset;
|
||||
break;
|
||||
stream->mappos += offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
if (stream->mapsize + offset < stream->mapsize)
|
||||
return -1;
|
||||
case SEEK_END:
|
||||
if (stream->mapsize + offset < stream->mapsize)
|
||||
goto error;
|
||||
|
||||
stream->mappos = stream->mapsize + offset;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return stream->mappos;
|
||||
stream->mappos = stream->mapsize + offset;
|
||||
break;
|
||||
}
|
||||
else
|
||||
return stream->mappos;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
ret = lseek(stream->fd, offset, whence);
|
||||
return ret < 0 ? -1 : ret;
|
||||
}
|
||||
|
||||
if (lseek(stream->fd, offset, whence) < 0)
|
||||
goto error;
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t filestream_tell(RFILE *stream)
|
||||
{
|
||||
if (!stream)
|
||||
return -1;
|
||||
#if defined(VITA) || defined(PSP)
|
||||
return sceIoLseek(stream->fd, 0, SEEK_CUR);
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
#if defined(__CELLOS_LV2__)
|
||||
uint64_t pos = 0;
|
||||
#endif
|
||||
if (!stream)
|
||||
goto error;
|
||||
#if defined(VITA) || defined(PSP)
|
||||
if (sceIoLseek(stream->fd, 0, SEEK_CUR) < 0)
|
||||
goto error;
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
if (cellFsLseek(stream->fd, 0, CELL_FS_SEEK_CUR, &pos) != CELL_FS_SUCCEEDED)
|
||||
return -1;
|
||||
return 0;
|
||||
goto error;
|
||||
#else
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
return ftell(stream->fp);
|
||||
else
|
||||
#endif
|
||||
#ifdef HAVE_MMAP
|
||||
/* Need to check stream->mapped because this function
|
||||
* is called in filestream_open() */
|
||||
if (stream->mapped && stream->hints & RFILE_HINT_MMAP)
|
||||
return stream->mappos;
|
||||
else
|
||||
/* Need to check stream->mapped because this function
|
||||
* is called in filestream_open() */
|
||||
if (stream->mapped && stream->hints & RFILE_HINT_MMAP)
|
||||
return stream->mappos;
|
||||
#endif
|
||||
return lseek(stream->fd, 0, SEEK_CUR);
|
||||
if (lseek(stream->fd, 0, SEEK_CUR) < 0)
|
||||
goto error;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
void filestream_rewind(RFILE *stream)
|
||||
|
@ -345,70 +347,85 @@ void filestream_rewind(RFILE *stream)
|
|||
ssize_t filestream_read(RFILE *stream, void *s, size_t len)
|
||||
{
|
||||
if (!stream || !s)
|
||||
return -1;
|
||||
goto error;
|
||||
#if defined(VITA) || defined(PSP)
|
||||
return sceIoRead(stream->fd, s, len);
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
uint64_t bytes_written;
|
||||
if (cellFsRead(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED)
|
||||
return -1;
|
||||
goto error;
|
||||
return bytes_written;
|
||||
#else
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
return fread(s, 1, len, stream->fp);
|
||||
else
|
||||
#endif
|
||||
#ifdef HAVE_MMAP
|
||||
if (stream->hints & RFILE_HINT_MMAP)
|
||||
{
|
||||
if (stream->mappos > stream->mapsize)
|
||||
return -1;
|
||||
if (stream->hints & RFILE_HINT_MMAP)
|
||||
{
|
||||
if (stream->mappos > stream->mapsize)
|
||||
goto error;
|
||||
|
||||
if (stream->mappos + len > stream->mapsize)
|
||||
len = stream->mapsize - stream->mappos;
|
||||
if (stream->mappos + len > stream->mapsize)
|
||||
len = stream->mapsize - stream->mappos;
|
||||
|
||||
memcpy(s, &stream->mapped[stream->mappos], len);
|
||||
stream->mappos += len;
|
||||
memcpy(s, &stream->mapped[stream->mappos], len);
|
||||
stream->mappos += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
else
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
return read(stream->fd, s, len);
|
||||
return read(stream->fd, s, len);
|
||||
#endif
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t filestream_write(RFILE *stream, const void *s, size_t len)
|
||||
{
|
||||
if (!stream)
|
||||
return -1;
|
||||
goto error;
|
||||
#if defined(VITA) || defined(PSP)
|
||||
return sceIoWrite(stream->fd, s, len);
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
uint64_t bytes_written;
|
||||
if (cellFsWrite(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED)
|
||||
return -1;
|
||||
goto error;
|
||||
return bytes_written;
|
||||
#else
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
return fwrite(s, 1, len, stream->fp);
|
||||
else
|
||||
#endif
|
||||
#ifdef HAVE_MMAP
|
||||
if (stream->hints & RFILE_HINT_MMAP)
|
||||
return -1;
|
||||
else
|
||||
if (stream->hints & RFILE_HINT_MMAP)
|
||||
goto error;
|
||||
#endif
|
||||
return write(stream->fd, s, len);
|
||||
return write(stream->fd, s, len);
|
||||
#endif
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int filestream_putc(RFILE *stream, int c)
|
||||
{
|
||||
if (!stream)
|
||||
return EOF;
|
||||
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
return fputc(c, stream->fp);
|
||||
#else
|
||||
/* unimplemented */
|
||||
return EOF;
|
||||
#endif
|
||||
}
|
||||
|
||||
int filestream_close(RFILE *stream)
|
||||
{
|
||||
if (!stream)
|
||||
return -1;
|
||||
goto error;
|
||||
|
||||
#if defined(VITA) || defined(PSP)
|
||||
if (stream->fd > 0)
|
||||
|
@ -430,12 +447,15 @@ int filestream_close(RFILE *stream)
|
|||
munmap(stream->mapped, stream->mapsize);
|
||||
#endif
|
||||
|
||||
if (stream->fd > 0)
|
||||
close(stream->fd);
|
||||
if (stream->fd > 0)
|
||||
close(stream->fd);
|
||||
#endif
|
||||
free(stream);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -534,5 +554,8 @@ bool filestream_write_file(const char *path, const void *data, ssize_t size)
|
|||
ret = filestream_write(file, data, size);
|
||||
filestream_close(file);
|
||||
|
||||
return (ret == size);
|
||||
if (ret != size)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,270 @@
|
|||
/* Copyright (C) 2010-2016 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (interface_stream.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <streams/interface_stream.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <streams/memory_stream.h>
|
||||
|
||||
struct intfstream_internal
|
||||
{
|
||||
enum intfstream_type type;
|
||||
|
||||
struct
|
||||
{
|
||||
RFILE *fp;
|
||||
} file;
|
||||
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
} buf;
|
||||
memstream_t *fp;
|
||||
bool writable;
|
||||
} memory;
|
||||
};
|
||||
|
||||
bool intfstream_resize(intfstream_internal_t *intf, intfstream_info_t *info)
|
||||
{
|
||||
if (!intf || !info)
|
||||
return false;
|
||||
|
||||
switch (intf->type)
|
||||
{
|
||||
case INTFSTREAM_FILE:
|
||||
break;
|
||||
case INTFSTREAM_MEMORY:
|
||||
intf->memory.buf.data = info->memory.buf.data;
|
||||
intf->memory.buf.size = info->memory.buf.size;
|
||||
|
||||
memstream_set_buffer(intf->memory.buf.data,
|
||||
intf->memory.buf.size);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool intfstream_open(intfstream_internal_t *intf, const char *path,
|
||||
unsigned mode, ssize_t len)
|
||||
{
|
||||
if (!intf)
|
||||
return false;
|
||||
|
||||
switch (intf->type)
|
||||
{
|
||||
case INTFSTREAM_FILE:
|
||||
intf->file.fp = filestream_open(path, mode, len);
|
||||
if (!intf->file.fp)
|
||||
return false;
|
||||
break;
|
||||
case INTFSTREAM_MEMORY:
|
||||
intf->memory.fp = memstream_open(intf->memory.writable);
|
||||
if (!intf->memory.fp)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int intfstream_close(intfstream_internal_t *intf)
|
||||
{
|
||||
if (!intf)
|
||||
return -1;
|
||||
|
||||
switch (intf->type)
|
||||
{
|
||||
case INTFSTREAM_FILE:
|
||||
return filestream_close(intf->file.fp);
|
||||
case INTFSTREAM_MEMORY:
|
||||
memstream_close(intf->memory.fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *intfstream_init(intfstream_info_t *info)
|
||||
{
|
||||
intfstream_internal_t *intf = NULL;
|
||||
if (!info)
|
||||
goto error;
|
||||
|
||||
intf = (intfstream_internal_t*)calloc(1, sizeof(*intf));
|
||||
|
||||
if (!intf)
|
||||
goto error;
|
||||
|
||||
intf->type = info->type;
|
||||
|
||||
switch (intf->type)
|
||||
{
|
||||
case INTFSTREAM_FILE:
|
||||
break;
|
||||
case INTFSTREAM_MEMORY:
|
||||
intf->memory.writable = info->memory.writable;
|
||||
if (!intfstream_resize(intf, info))
|
||||
goto error;
|
||||
break;
|
||||
}
|
||||
|
||||
return intf;
|
||||
|
||||
error:
|
||||
if (intf)
|
||||
free(intf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int intfstream_seek(intfstream_internal_t *intf, int offset, int whence)
|
||||
{
|
||||
if (!intf)
|
||||
return -1;
|
||||
|
||||
switch (intf->type)
|
||||
{
|
||||
case INTFSTREAM_FILE:
|
||||
return filestream_seek(intf->file.fp, offset, whence);
|
||||
case INTFSTREAM_MEMORY:
|
||||
return memstream_seek(intf->memory.fp, offset, whence);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t intfstream_read(intfstream_internal_t *intf, void *s, size_t len)
|
||||
{
|
||||
if (!intf)
|
||||
return 0;
|
||||
|
||||
switch (intf->type)
|
||||
{
|
||||
case INTFSTREAM_FILE:
|
||||
return filestream_read(intf->file.fp, s, len);
|
||||
case INTFSTREAM_MEMORY:
|
||||
return memstream_read(intf->memory.fp, s, len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t intfstream_write(intfstream_internal_t *intf,
|
||||
const void *s, size_t len)
|
||||
{
|
||||
if (!intf)
|
||||
return 0;
|
||||
|
||||
switch (intf->type)
|
||||
{
|
||||
case INTFSTREAM_FILE:
|
||||
return filestream_write(intf->file.fp, s, len);
|
||||
case INTFSTREAM_MEMORY:
|
||||
return memstream_write(intf->memory.fp, s, len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *intfstream_gets(intfstream_internal_t *intf,
|
||||
char *buffer, size_t len)
|
||||
{
|
||||
if (!intf)
|
||||
return NULL;
|
||||
|
||||
switch (intf->type)
|
||||
{
|
||||
case INTFSTREAM_FILE:
|
||||
/* unimplemented */
|
||||
break;
|
||||
case INTFSTREAM_MEMORY:
|
||||
return memstream_gets(intf->memory.fp, buffer, len);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int intfstream_getc(intfstream_internal_t *intf)
|
||||
{
|
||||
if (!intf)
|
||||
return 0;
|
||||
|
||||
switch (intf->type)
|
||||
{
|
||||
case INTFSTREAM_FILE:
|
||||
/* unimplemented */
|
||||
break;
|
||||
case INTFSTREAM_MEMORY:
|
||||
return memstream_getc(intf->memory.fp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int intfstream_tell(intfstream_internal_t *intf)
|
||||
{
|
||||
if (!intf)
|
||||
return -1;
|
||||
|
||||
switch (intf->type)
|
||||
{
|
||||
case INTFSTREAM_FILE:
|
||||
return filestream_tell(intf->file.fp);
|
||||
case INTFSTREAM_MEMORY:
|
||||
return memstream_pos(intf->memory.fp);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void intfstream_rewind(intfstream_internal_t *intf)
|
||||
{
|
||||
switch (intf->type)
|
||||
{
|
||||
case INTFSTREAM_FILE:
|
||||
filestream_rewind(intf->file.fp);
|
||||
break;
|
||||
case INTFSTREAM_MEMORY:
|
||||
memstream_rewind(intf->memory.fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void intfstream_putc(intfstream_internal_t *intf, int c)
|
||||
{
|
||||
if (!intf)
|
||||
return;
|
||||
|
||||
switch (intf->type)
|
||||
{
|
||||
case INTFSTREAM_FILE:
|
||||
filestream_putc(intf->file.fp, c);
|
||||
break;
|
||||
case INTFSTREAM_MEMORY:
|
||||
memstream_putc(intf->memory.fp, c);
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -32,11 +32,19 @@ static size_t last_file_size = 0;
|
|||
|
||||
struct memstream
|
||||
{
|
||||
uint8_t *m_buf;
|
||||
size_t m_size;
|
||||
size_t m_ptr;
|
||||
uint8_t *buf;
|
||||
size_t size;
|
||||
size_t ptr;
|
||||
size_t max_ptr;
|
||||
unsigned writing;
|
||||
};
|
||||
|
||||
static void memstream_update_pos(memstream_t *stream)
|
||||
{
|
||||
if (stream->ptr > stream->max_ptr)
|
||||
stream->max_ptr = stream->ptr;
|
||||
}
|
||||
|
||||
void memstream_set_buffer(uint8_t *buffer, size_t size)
|
||||
{
|
||||
g_buffer = buffer;
|
||||
|
@ -48,21 +56,27 @@ size_t memstream_get_last_size(void)
|
|||
return last_file_size;
|
||||
}
|
||||
|
||||
static void memstream_init(memstream_t *stream, uint8_t *buffer, size_t max_size)
|
||||
static void memstream_init(memstream_t *stream,
|
||||
uint8_t *buffer, size_t max_size, unsigned writing)
|
||||
{
|
||||
stream->m_buf = buffer;
|
||||
stream->m_size = max_size;
|
||||
stream->m_ptr = 0;
|
||||
if (!stream)
|
||||
return;
|
||||
|
||||
stream->buf = buffer;
|
||||
stream->size = max_size;
|
||||
stream->ptr = 0;
|
||||
stream->max_ptr = 0;
|
||||
stream->writing = writing;
|
||||
}
|
||||
|
||||
memstream_t *memstream_open(void)
|
||||
memstream_t *memstream_open(unsigned writing)
|
||||
{
|
||||
memstream_t *stream;
|
||||
if (!g_buffer || !g_size)
|
||||
return NULL;
|
||||
|
||||
stream = (memstream_t*)calloc(1, sizeof(*stream));
|
||||
memstream_init(stream, g_buffer, g_size);
|
||||
memstream_init(stream, g_buffer, g_size, writing);
|
||||
|
||||
g_buffer = NULL;
|
||||
g_size = 0;
|
||||
|
@ -71,29 +85,44 @@ memstream_t *memstream_open(void)
|
|||
|
||||
void memstream_close(memstream_t *stream)
|
||||
{
|
||||
last_file_size = stream->m_ptr;
|
||||
if (!stream)
|
||||
return;
|
||||
|
||||
last_file_size = stream->writing ? stream->max_ptr : stream->size;
|
||||
free(stream);
|
||||
}
|
||||
|
||||
size_t memstream_read(memstream_t *stream, void *data, size_t bytes)
|
||||
{
|
||||
size_t avail = stream->m_size - stream->m_ptr;
|
||||
size_t avail = 0;
|
||||
|
||||
if (!stream)
|
||||
return 0;
|
||||
|
||||
avail = stream->size - stream->ptr;
|
||||
if (bytes > avail)
|
||||
bytes = avail;
|
||||
|
||||
memcpy(data, stream->m_buf + stream->m_ptr, bytes);
|
||||
stream->m_ptr += bytes;
|
||||
memcpy(data, stream->buf + stream->ptr, bytes);
|
||||
stream->ptr += bytes;
|
||||
memstream_update_pos(stream);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
size_t memstream_write(memstream_t *stream, const void *data, size_t bytes)
|
||||
{
|
||||
size_t avail = stream->m_size - stream->m_ptr;
|
||||
size_t avail = 0;
|
||||
|
||||
if (!stream)
|
||||
return 0;
|
||||
|
||||
avail = stream->size - stream->ptr;
|
||||
if (bytes > avail)
|
||||
bytes = avail;
|
||||
|
||||
memcpy(stream->m_buf + stream->m_ptr, data, bytes);
|
||||
stream->m_ptr += bytes;
|
||||
memcpy(stream->buf + stream->ptr, data, bytes);
|
||||
stream->ptr += bytes;
|
||||
memstream_update_pos(stream);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
@ -107,26 +136,32 @@ int memstream_seek(memstream_t *stream, int offset, int whence)
|
|||
ptr = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
ptr = stream->m_ptr + offset;
|
||||
ptr = stream->ptr + offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
ptr = stream->m_size + offset;
|
||||
ptr = (stream->writing ? stream->max_ptr : stream->size) + offset;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ptr <= stream->m_size)
|
||||
if (ptr <= stream->size)
|
||||
{
|
||||
stream->m_ptr = ptr;
|
||||
stream->ptr = ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void memstream_rewind(memstream_t *stream)
|
||||
{
|
||||
memstream_seek(stream, 0L, SEEK_SET);
|
||||
}
|
||||
|
||||
size_t memstream_pos(memstream_t *stream)
|
||||
{
|
||||
return stream->m_ptr;
|
||||
return stream->ptr;
|
||||
}
|
||||
|
||||
char *memstream_gets(memstream_t *stream, char *buffer, size_t len)
|
||||
|
@ -136,7 +171,20 @@ char *memstream_gets(memstream_t *stream, char *buffer, size_t len)
|
|||
|
||||
int memstream_getc(memstream_t *stream)
|
||||
{
|
||||
if (stream->m_ptr >= stream->m_size)
|
||||
int ret = 0;
|
||||
if (stream->ptr >= stream->size)
|
||||
return EOF;
|
||||
return stream->m_buf[stream->m_ptr++];
|
||||
ret = stream->buf[stream->ptr++];
|
||||
|
||||
memstream_update_pos(stream);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void memstream_putc(memstream_t *stream, int c)
|
||||
{
|
||||
if (stream->ptr < stream->size)
|
||||
stream->buf[stream->ptr++] = c;
|
||||
|
||||
memstream_update_pos(stream);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue