cake
/
libcasio
Archived
1
1
Fork 0
This repository has been archived on 2024-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
libcasio/lib/stream/builtin/limited.c

152 lines
3.7 KiB
C

/* ****************************************************************************
* stream/builtin/limited.c -- built-in limited stream.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libcasio.
* libcasio is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libcasio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libcasio; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************* */
#include "builtin.h"
/* Cookie structure. */
typedef struct {
char _magic[8];
casio_stream_t *_stream;
size_t _left;
} limited_cookie_t;
/* ---
* Callbacks.
* --- */
/**
* casio_limited_read:
* Read from a limited stream.
*
* @arg vcookie the cookie (uncasted).
* @arg data the data pointer.
* @arg size the data size.
* @arg timeout the timeout (in ms).
* @return the error code (0 if ok).
*/
CASIO_LOCAL int casio_limited_read(void *vcookie, unsigned char *dest,
size_t size, unsigned int timeout)
{
int err; limited_cookie_t *cookie = (void*)vcookie;
size_t left;
if (size > cookie->_left) {
/* First, skip the required bytes. */
left = cookie->_left;
cookie->_left = 0;
if ((err = casio_skip(cookie->_stream, left)))
return (err);
/* Once the skip is done successfully, we return that we
* have an EOF. */
return (casio_error_eof);
}
if ((err = casio_read(cookie->_stream, dest, size, timeout))) {
cookie->_left = 0; /* XXX: depends on the error? */
return (err);
}
cookie->_left -= size;
return (0);
}
/**
* casio_limited_close:
* Close a limited stream.
*
* @arg vcookie the cookie (uncasted).
* @return the error code (0 if ok).
*/
CASIO_LOCAL int casio_limited_close(void *vcookie)
{
casio_free(vcookie);
return (0);
}
/* Callbacks. */
CASIO_LOCAL const casio_streamfuncs_t casio_limited_callbacks = {
(casio_stream_close_t *)casio_limited_close,
(casio_stream_read_t *)casio_limited_read,
NULL, NULL,
NULL, NULL, NULL, NULL
};
/* ---
* Main functions.
* --- */
/**
* casio_open_limited:
* Open a limited stream.
*
* @arg stream the stream to make.
* @arg original the original stream.
* @arg size the size the limited buffer is limited to.
* @return the error (0 if ok).
*/
int CASIO_EXPORT casio_open_limited(casio_stream_t **stream,
casio_stream_t *original, size_t size)
{
limited_cookie_t *cookie = NULL;
/* FIXME: check original stream */
/* allocate the cookie */
cookie = casio_alloc(1, sizeof(limited_cookie_t));
if (!cookie)
return (casio_error_alloc);
/* Fill the cookie. */
memcpy(cookie->_magic, "LIMITED\x7F", 8);
cookie->_stream = original;
cookie->_left = size;
/* Initialize da stream. */
return (casio_open_stream(stream,
casio_get_openmode(original) & CASIO_OPENMODE_READ,
cookie, &casio_limited_callbacks, 0));
}
/**
* casio_empty_limited:
* Empty a limited stream.
*
* @arg stream the stream to empty.
* @return the error code (0 if ok).
*/
int CASIO_EXPORT casio_empty_limited(casio_stream_t *stream)
{
int err; limited_cookie_t *cookie = (void*)casio_get_cookie(stream);
if (!cookie || memcmp(cookie->_magic, "LIMITED\x7F", 8))
return (casio_error_op);
err = casio_skip(cookie->_stream, cookie->_left);
cookie->_left = 0;
return (err);
}