2013-01-11 01:48:46 +08:00
|
|
|
#include "stream.h"
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
struct _internal_foug_stream
|
|
|
|
{
|
|
|
|
void* cookie;
|
|
|
|
foug_stream_manip_t manip;
|
|
|
|
};
|
|
|
|
|
|
|
|
foug_stream_t* foug_stream_create(foug_malloc_func_t func, void* data, foug_stream_manip_t manip)
|
|
|
|
{
|
2013-01-25 01:38:43 +08:00
|
|
|
foug_stream_t* stream;
|
|
|
|
|
2013-01-11 01:48:46 +08:00
|
|
|
if (func == NULL)
|
|
|
|
return NULL;
|
2013-01-25 01:38:43 +08:00
|
|
|
stream = (*func)(sizeof(struct _internal_foug_stream));
|
2013-01-11 01:48:46 +08:00
|
|
|
if (stream != NULL) {
|
|
|
|
stream->cookie = data;
|
|
|
|
stream->manip = manip;
|
|
|
|
}
|
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
|
2013-03-02 04:37:31 +08:00
|
|
|
/*!
|
|
|
|
* \brief Create a null stream manipulator
|
|
|
|
*/
|
2013-01-11 01:48:46 +08:00
|
|
|
foug_stream_manip_t foug_stream_manip_null()
|
|
|
|
{
|
|
|
|
foug_stream_manip_t manip;
|
|
|
|
memset(&manip, 0, sizeof(foug_stream_manip_t));
|
|
|
|
return manip;
|
|
|
|
}
|
|
|
|
|
2013-01-15 02:30:42 +08:00
|
|
|
static foug_bool_t foug_stream_stdio_at_end(foug_stream_t* stream)
|
2013-01-11 01:48:46 +08:00
|
|
|
{
|
|
|
|
return feof((FILE*) stream->cookie);
|
|
|
|
}
|
|
|
|
|
2013-01-15 17:40:35 +08:00
|
|
|
static int32_t foug_stream_stdio_error(foug_stream_t* stream)
|
2013-01-11 01:48:46 +08:00
|
|
|
{
|
2013-01-15 17:40:35 +08:00
|
|
|
return ferror((FILE*) stream->cookie);
|
|
|
|
}
|
2013-01-11 01:48:46 +08:00
|
|
|
|
2013-01-15 02:30:42 +08:00
|
|
|
static size_t foug_stream_stdio_read(foug_stream_t* stream,
|
|
|
|
void* ptr,
|
|
|
|
size_t item_size,
|
|
|
|
size_t item_count)
|
2013-01-11 01:48:46 +08:00
|
|
|
{
|
2013-01-15 02:30:42 +08:00
|
|
|
return fread(ptr, item_size, item_count, (FILE*) stream->cookie);
|
2013-01-11 01:48:46 +08:00
|
|
|
}
|
|
|
|
|
2013-01-15 02:30:42 +08:00
|
|
|
static size_t foug_stream_stdio_write(foug_stream_t* stream,
|
|
|
|
const void* ptr,
|
|
|
|
size_t item_size,
|
|
|
|
size_t item_count)
|
2013-01-11 01:48:46 +08:00
|
|
|
{
|
2013-01-15 02:30:42 +08:00
|
|
|
return fwrite(ptr, item_size, item_count, (FILE*) stream->cookie);
|
2013-01-11 01:48:46 +08:00
|
|
|
}
|
|
|
|
|
2013-03-02 04:37:31 +08:00
|
|
|
/*!
|
|
|
|
* \brief Create a stream manipulator for standard FILE*
|
|
|
|
*/
|
2013-01-11 01:48:46 +08:00
|
|
|
foug_stream_manip_t foug_stream_manip_stdio()
|
|
|
|
{
|
|
|
|
foug_stream_manip_t manip;
|
2013-01-24 18:29:51 +08:00
|
|
|
manip.at_end_func = foug_stream_stdio_at_end;
|
|
|
|
manip.error_func = foug_stream_stdio_error;
|
|
|
|
manip.read_func = foug_stream_stdio_read;
|
|
|
|
manip.write_func = foug_stream_stdio_write;
|
2013-01-11 01:48:46 +08:00
|
|
|
return manip;
|
|
|
|
}
|
|
|
|
|
2013-01-15 02:30:42 +08:00
|
|
|
foug_bool_t foug_stream_at_end(foug_stream_t* stream)
|
2013-01-11 01:48:46 +08:00
|
|
|
{
|
|
|
|
if (stream != NULL && stream->manip.at_end_func != NULL)
|
2013-03-02 04:37:31 +08:00
|
|
|
return stream->manip.at_end_func(stream);
|
2013-01-11 01:48:46 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-03-02 04:37:31 +08:00
|
|
|
/*!
|
|
|
|
* \brief Check error indicator
|
|
|
|
*
|
|
|
|
* Checks if the error indicator associated with \p stream is set, returning a value different from
|
|
|
|
* zero if it is.
|
|
|
|
*
|
|
|
|
* This indicator is generally set by a previous operation on the \p stream that failed.
|
|
|
|
*/
|
2013-01-15 17:40:35 +08:00
|
|
|
int foug_stream_error(foug_stream_t* stream)
|
2013-01-11 01:48:46 +08:00
|
|
|
{
|
2013-01-15 17:40:35 +08:00
|
|
|
if (stream != NULL && stream->manip.error_func != NULL)
|
2013-03-02 04:37:31 +08:00
|
|
|
return stream->manip.error_func(stream);
|
2013-01-15 17:40:35 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2013-01-11 01:48:46 +08:00
|
|
|
|
2013-03-02 04:37:31 +08:00
|
|
|
/*!
|
|
|
|
* \brief Read block of data from stream
|
|
|
|
*
|
|
|
|
* Reads an array of \p item_count elements, each one with a \p item_size of size bytes, from the
|
|
|
|
* \p stream and stores them in the block of memory specified by \p ptr.
|
|
|
|
*
|
|
|
|
* The total amount of bytes read if successful is (item_size * item_count).
|
|
|
|
*
|
|
|
|
* \return The total number of elements successfully read is returned.
|
|
|
|
* If this number differs from the \p item_count argument, either a reading error occurred
|
|
|
|
* or the end-of-file was reached while reading. In both cases, the proper indicator is set,
|
|
|
|
* which can be checked with foug_stream_error() and foug_stream_at_end(), respectively.
|
|
|
|
* If either \p item_size or \p item_count is zero, the function returns zero and both the
|
|
|
|
* stream state and the content pointed by \p ptr remain unchanged.
|
|
|
|
*/
|
2013-01-15 02:30:42 +08:00
|
|
|
size_t foug_stream_read(foug_stream_t* stream, void *ptr, size_t item_size, size_t item_count)
|
2013-01-11 01:48:46 +08:00
|
|
|
{
|
|
|
|
if (stream != NULL && stream->manip.read_func != NULL)
|
2013-03-02 04:37:31 +08:00
|
|
|
return stream->manip.read_func(stream, ptr, item_size, item_count);
|
2013-01-11 01:48:46 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-03-02 04:37:31 +08:00
|
|
|
/*!
|
|
|
|
* \brief Write block of data to stream
|
|
|
|
*
|
|
|
|
* Writes an array of \p item_count elements, each one with a \p item_size of size bytes, from the
|
|
|
|
* block of memory pointed by \p ptr to the current position in the \p stream.
|
|
|
|
*
|
|
|
|
* The total amount of bytes written is (item_size * item_count).
|
|
|
|
*/
|
2013-01-15 02:30:42 +08:00
|
|
|
size_t foug_stream_write(foug_stream_t* stream, const void *ptr, size_t item_size, size_t item_count)
|
2013-01-11 01:48:46 +08:00
|
|
|
{
|
|
|
|
if (stream != NULL && stream->manip.write_func != NULL)
|
2013-03-02 04:37:31 +08:00
|
|
|
return stream->manip.write_func(stream, ptr, item_size, item_count);
|
2013-01-11 01:48:46 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* foug_stream_get_cookie(const foug_stream_t* stream)
|
|
|
|
{
|
|
|
|
return stream != NULL ? stream->cookie : NULL;
|
|
|
|
}
|
2013-02-05 19:24:13 +08:00
|
|
|
|
|
|
|
void foug_stream_set_cookie(foug_stream_t* stream, void* data)
|
|
|
|
{
|
|
|
|
if (stream != NULL)
|
|
|
|
stream->cookie = data;
|
|
|
|
}
|