Grab all MIO changes from uctags
This commit is contained in:
parent
580beba0c7
commit
a5dea8091b
382
ctags/main/mio.c
382
ctags/main/mio.c
@ -18,6 +18,22 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QUALIFIER
|
||||
#include "general.h" /* must always come first */
|
||||
|
||||
#include "routines.h"
|
||||
#include "debug.h"
|
||||
#else
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_STDBOOL_H
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "mio.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
@ -27,6 +43,63 @@
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef QUALIFIER
|
||||
#define xMalloc(n,Type) (Type *)eMalloc((size_t)(n) * sizeof (Type))
|
||||
#define xCalloc(n,Type) (Type *)eCalloc((size_t)(n), sizeof (Type))
|
||||
#define xRealloc(p,n,Type) (Type *)eRealloc((p), (n) * sizeof (Type))
|
||||
|
||||
extern void *eMalloc (const size_t size)
|
||||
{
|
||||
void *buffer = malloc (size);
|
||||
|
||||
if (buffer == NULL)
|
||||
{
|
||||
fprintf(stderr, "out of memory");
|
||||
abort ();
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
extern void *eCalloc (const size_t count, const size_t size)
|
||||
{
|
||||
void *buffer = calloc (count, size);
|
||||
|
||||
if (buffer == NULL)
|
||||
{
|
||||
fprintf(stderr, "out of memory");
|
||||
abort ();
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
extern void *eRealloc (void *const ptr, const size_t size)
|
||||
{
|
||||
void *buffer;
|
||||
if (ptr == NULL)
|
||||
buffer = eMalloc (size);
|
||||
else
|
||||
{
|
||||
buffer = realloc (ptr, size);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
fprintf(stderr, "out of memory");
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
extern void eFree (void *const ptr)
|
||||
{
|
||||
free (ptr);
|
||||
}
|
||||
|
||||
# define Assert(c)
|
||||
# define AssertNotReached()
|
||||
#endif
|
||||
|
||||
/* minimal reallocation chunk size */
|
||||
#define MIO_CHUNK_SIZE 4096
|
||||
|
||||
@ -42,9 +115,12 @@
|
||||
* file based operations and in-memory operations. Its goal is to ease the port
|
||||
* of an application that uses C file I/O API to perform in-memory operations.
|
||||
*
|
||||
* A #MIO object is created using mio_new_file() or mio_new_memory(), depending
|
||||
* on whether you want file or in-memory operations, and destroyed using
|
||||
* mio_free(). There is also some other convenient API to create file-based
|
||||
* A #MIO object is created using mio_new_file(), mio_new_memory() or mio_new_mio(),
|
||||
* depending on whether you want file or in-memory operations.
|
||||
* Its life is managed by reference counting. Just after calling one of functions
|
||||
* for creating, the count is 1. mio_ref() increments the counter. mio_free()
|
||||
* decrements it. When the counter becomes 0, the #MIO object will be destroyed
|
||||
* in mio_free(). There is also some other convenient API to create file-based
|
||||
* #MIO objects for more complex cases, such as mio_new_file_full() and
|
||||
* mio_new_fp().
|
||||
*
|
||||
@ -58,6 +134,43 @@
|
||||
*/
|
||||
|
||||
|
||||
typedef struct _MIOUserData MIOUserData;
|
||||
struct _MIOUserData {
|
||||
void *d;
|
||||
MIODestroyNotify f;
|
||||
};
|
||||
|
||||
/**
|
||||
* MIO:
|
||||
*
|
||||
* An object representing a #MIO stream. No assumptions should be made about
|
||||
* what compose this object, and none of its fields should be accessed directly.
|
||||
*/
|
||||
struct _MIO {
|
||||
/*< private >*/
|
||||
MIOType type;
|
||||
unsigned int refcount;
|
||||
union {
|
||||
struct {
|
||||
FILE *fp;
|
||||
MIOFCloseFunc close_func;
|
||||
} file;
|
||||
struct {
|
||||
unsigned char *buf;
|
||||
int ungetch;
|
||||
size_t pos;
|
||||
size_t size;
|
||||
size_t allocated_size;
|
||||
MIOReallocFunc realloc_func;
|
||||
MIODestroyNotify free_func;
|
||||
bool error;
|
||||
bool eof;
|
||||
} mem;
|
||||
} impl;
|
||||
MIOUserData udata;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* mio_new_file_full:
|
||||
* @filename: Filename to open, passed as-is to @open_func as the first argument
|
||||
@ -93,14 +206,14 @@ MIO *mio_new_file_full (const char *filename,
|
||||
/* we need to create the MIO object first, because we may not be able to close
|
||||
* the opened file if the user passed NULL as the close function, which means
|
||||
* that everything must succeed if we've opened the file successfully */
|
||||
mio = malloc (sizeof *mio);
|
||||
mio = xMalloc (1, MIO);
|
||||
if (mio)
|
||||
{
|
||||
FILE *fp = open_func (filename, mode);
|
||||
|
||||
if (! fp)
|
||||
{
|
||||
free (mio);
|
||||
eFree (mio);
|
||||
mio = NULL;
|
||||
}
|
||||
else
|
||||
@ -108,6 +221,9 @@ MIO *mio_new_file_full (const char *filename,
|
||||
mio->type = MIO_TYPE_FILE;
|
||||
mio->impl.file.fp = fp;
|
||||
mio->impl.file.close_func = close_func;
|
||||
mio->refcount = 1;
|
||||
mio->udata.d = NULL;
|
||||
mio->udata.f = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,12 +276,15 @@ MIO *mio_new_fp (FILE *fp, MIOFCloseFunc close_func)
|
||||
if (!fp)
|
||||
return NULL;
|
||||
|
||||
mio = malloc (sizeof *mio);
|
||||
mio = xMalloc (1, MIO);
|
||||
if (mio)
|
||||
{
|
||||
mio->type = MIO_TYPE_FILE;
|
||||
mio->impl.file.fp = fp;
|
||||
mio->impl.file.close_func = close_func;
|
||||
mio->refcount = 1;
|
||||
mio->udata.d = NULL;
|
||||
mio->udata.f = NULL;
|
||||
}
|
||||
|
||||
return mio;
|
||||
@ -214,7 +333,7 @@ MIO *mio_new_memory (unsigned char *data,
|
||||
{
|
||||
MIO *mio;
|
||||
|
||||
mio = malloc (sizeof *mio);
|
||||
mio = xMalloc (1, MIO);
|
||||
if (mio)
|
||||
{
|
||||
mio->type = MIO_TYPE_MEMORY;
|
||||
@ -227,11 +346,89 @@ MIO *mio_new_memory (unsigned char *data,
|
||||
mio->impl.mem.free_func = free_func;
|
||||
mio->impl.mem.eof = false;
|
||||
mio->impl.mem.error = false;
|
||||
mio->refcount = 1;
|
||||
mio->udata.d = NULL;
|
||||
mio->udata.f = NULL;
|
||||
}
|
||||
|
||||
return mio;
|
||||
}
|
||||
|
||||
/**
|
||||
* mio_new_mio:
|
||||
* @base: The original mio
|
||||
* @start: stream offset of the @base where new mio starts
|
||||
* @size: the length of the data copied from @base to new mio
|
||||
*
|
||||
* Creates a new #MIO object by copying data from existing #MIO (@base).
|
||||
* The range for copying are given with @start and @size.
|
||||
* Copying data at the range from @start to the end of @base is
|
||||
* done if 0 is given as @size.
|
||||
*
|
||||
* If @size(!= 0) is larger than the length from @start to the end of
|
||||
* @base, %NULL is return.
|
||||
*
|
||||
* The function doesn't move the file position of @base.
|
||||
*
|
||||
* Free-function: mio_free()
|
||||
*
|
||||
*/
|
||||
|
||||
MIO *mio_new_mio (MIO *base, long start, size_t size)
|
||||
{
|
||||
unsigned char *data;
|
||||
long original_pos;
|
||||
MIO *submio;
|
||||
size_t r;
|
||||
|
||||
original_pos = mio_tell (base);
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
long end;
|
||||
|
||||
if (mio_seek (base, 0, SEEK_END) != 0)
|
||||
return NULL;
|
||||
end = mio_tell (base);
|
||||
size = end - start;
|
||||
Assert (size >= 0);
|
||||
}
|
||||
|
||||
if (mio_seek (base, start, SEEK_SET) != 0)
|
||||
return NULL;
|
||||
|
||||
data = xMalloc (size, unsigned char);
|
||||
r= mio_read (base, data, 1, size);
|
||||
mio_seek (base, original_pos, SEEK_SET);
|
||||
|
||||
if (r != size)
|
||||
goto cleanup;
|
||||
|
||||
submio = mio_new_memory (data, size, eRealloc, eFree);
|
||||
if (! submio)
|
||||
goto cleanup;
|
||||
|
||||
return submio;
|
||||
|
||||
cleanup:
|
||||
eFree (data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* mio_ref:
|
||||
* @mio: A #MIO object
|
||||
*
|
||||
* Increments the reference counter of a #MIO.
|
||||
*
|
||||
* Returns: passed @mio.
|
||||
*/
|
||||
MIO *mio_ref (MIO *mio)
|
||||
{
|
||||
mio->refcount++;
|
||||
return mio;
|
||||
}
|
||||
|
||||
/**
|
||||
* mio_file_get_fp:
|
||||
* @mio: A #MIO object
|
||||
@ -288,7 +485,8 @@ unsigned char *mio_memory_get_data (MIO *mio, size_t *size)
|
||||
* mio_free:
|
||||
* @mio: A #MIO object
|
||||
*
|
||||
* Destroys a #MIO object.
|
||||
* Decrements the reference counter of a #MIO and destroys the #MIO
|
||||
* object if its counter becomes 0.
|
||||
*
|
||||
* Returns: Error code obtained from the registered MIOFCloseFunc or 0 on success.
|
||||
*/
|
||||
@ -298,6 +496,12 @@ int mio_free (MIO *mio)
|
||||
|
||||
if (mio)
|
||||
{
|
||||
if (--mio->refcount)
|
||||
return 0;
|
||||
|
||||
if (mio->udata.d && mio->udata.f)
|
||||
mio->udata.f (mio->udata.d);
|
||||
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
{
|
||||
if (mio->impl.file.close_func)
|
||||
@ -305,7 +509,7 @@ int mio_free (MIO *mio)
|
||||
mio->impl.file.close_func = NULL;
|
||||
mio->impl.file.fp = NULL;
|
||||
}
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
{
|
||||
if (mio->impl.mem.free_func)
|
||||
mio->impl.mem.free_func (mio->impl.mem.buf);
|
||||
@ -318,8 +522,10 @@ int mio_free (MIO *mio)
|
||||
mio->impl.mem.eof = false;
|
||||
mio->impl.mem.error = false;
|
||||
}
|
||||
else
|
||||
AssertNotReached ();
|
||||
|
||||
free (mio);
|
||||
eFree (mio);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -347,7 +553,7 @@ size_t mio_read (MIO *mio,
|
||||
{
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
return fread (ptr_, size, nmemb, mio->impl.file.fp);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
{
|
||||
size_t n_read = 0;
|
||||
|
||||
@ -382,6 +588,11 @@ size_t mio_read (MIO *mio,
|
||||
|
||||
return n_read;
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertNotReached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -490,7 +701,7 @@ size_t mio_write (MIO *mio,
|
||||
{
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
return fwrite (ptr, size, nmemb, mio->impl.file.fp);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
{
|
||||
size_t n_written = 0;
|
||||
|
||||
@ -506,6 +717,11 @@ size_t mio_write (MIO *mio,
|
||||
|
||||
return n_written;
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertNotReached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -522,7 +738,7 @@ int mio_putc (MIO *mio, int c)
|
||||
{
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
return fputc (c, mio->impl.file.fp);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
{
|
||||
int rv = EOF;
|
||||
|
||||
@ -535,6 +751,11 @@ int mio_putc (MIO *mio, int c)
|
||||
|
||||
return rv;
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertNotReached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -550,7 +771,7 @@ int mio_puts (MIO *mio, const char *s)
|
||||
{
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
return fputs (s, mio->impl.file.fp);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
{
|
||||
int rv = EOF;
|
||||
size_t len;
|
||||
@ -565,6 +786,11 @@ int mio_puts (MIO *mio, const char *s)
|
||||
|
||||
return rv;
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertNotReached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -583,7 +809,7 @@ int mio_vprintf (MIO *mio, const char *format, va_list ap)
|
||||
{
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
return vfprintf (mio->impl.file.fp, format, ap);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
{
|
||||
int rv = -1;
|
||||
size_t n;
|
||||
@ -623,6 +849,11 @@ int mio_vprintf (MIO *mio, const char *format, va_list ap)
|
||||
|
||||
return rv;
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertNotReached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -662,7 +893,7 @@ int mio_getc (MIO *mio)
|
||||
{
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
return fgetc (mio->impl.file.fp);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
{
|
||||
int rv = EOF;
|
||||
|
||||
@ -682,6 +913,11 @@ int mio_getc (MIO *mio)
|
||||
|
||||
return rv;
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertNotReached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -704,7 +940,7 @@ int mio_ungetc (MIO *mio, int ch)
|
||||
{
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
return ungetc (ch, mio->impl.file.fp);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
{
|
||||
int rv = EOF;
|
||||
|
||||
@ -717,6 +953,11 @@ int mio_ungetc (MIO *mio, int ch)
|
||||
|
||||
return rv;
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertNotReached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -735,28 +976,35 @@ char *mio_gets (MIO *mio, char *s, size_t size)
|
||||
{
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
return fgets (s, (int)size, mio->impl.file.fp);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
{
|
||||
char *rv = NULL;
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
size_t i = 0;
|
||||
bool newline = false;
|
||||
/* Avoiding dereference inside the for loop below improves
|
||||
* performance so we do it here. */
|
||||
size_t pos = mio->impl.mem.pos;
|
||||
size_t buf_size = mio->impl.mem.size;
|
||||
unsigned char *buf = mio->impl.mem.buf;
|
||||
|
||||
if (mio->impl.mem.ungetch != EOF)
|
||||
{
|
||||
s[i] = (char)mio->impl.mem.ungetch;
|
||||
mio->impl.mem.ungetch = EOF;
|
||||
mio->impl.mem.pos++;
|
||||
pos++;
|
||||
i++;
|
||||
}
|
||||
for (; mio->impl.mem.pos < mio->impl.mem.size && i < (size - 1); i++)
|
||||
for (; pos < buf_size && i < (size - 1); i++)
|
||||
{
|
||||
s[i] = (char)mio->impl.mem.buf[mio->impl.mem.pos];
|
||||
mio->impl.mem.pos++;
|
||||
s[i] = (char)buf[pos];
|
||||
pos++;
|
||||
if (s[i] == '\n')
|
||||
{
|
||||
i++;
|
||||
newline = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -765,12 +1013,19 @@ char *mio_gets (MIO *mio, char *s, size_t size)
|
||||
s[i] = 0;
|
||||
rv = s;
|
||||
}
|
||||
if (mio->impl.mem.pos >= mio->impl.mem.size)
|
||||
if (!newline && pos >= buf_size)
|
||||
mio->impl.mem.eof = true;
|
||||
mio->impl.mem.pos = pos;
|
||||
mio->impl.mem.size = buf_size;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertNotReached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -784,11 +1039,13 @@ void mio_clearerr (MIO *mio)
|
||||
{
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
clearerr (mio->impl.file.fp);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
{
|
||||
mio->impl.mem.error = false;
|
||||
mio->impl.mem.eof = false;
|
||||
}
|
||||
else
|
||||
AssertNotReached ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -804,8 +1061,13 @@ int mio_eof (MIO *mio)
|
||||
{
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
return feof (mio->impl.file.fp);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
return mio->impl.mem.eof != false;
|
||||
else
|
||||
{
|
||||
AssertNotReached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -821,8 +1083,13 @@ int mio_error (MIO *mio)
|
||||
{
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
return ferror (mio->impl.file.fp);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
return mio->impl.mem.error != false;
|
||||
else
|
||||
{
|
||||
AssertNotReached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -843,7 +1110,7 @@ int mio_seek (MIO *mio, long offset, int whence)
|
||||
{
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
return fseek (mio->impl.file.fp, offset, whence);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
{
|
||||
/* FIXME: should we support seeking out of bounds like lseek() seems to do? */
|
||||
int rv = -1;
|
||||
@ -894,6 +1161,12 @@ int mio_seek (MIO *mio, long offset, int whence)
|
||||
|
||||
return rv;
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertNotReached ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -910,7 +1183,7 @@ long mio_tell (MIO *mio)
|
||||
{
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
return ftell (mio->impl.file.fp);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
{
|
||||
long rv = -1;
|
||||
|
||||
@ -925,6 +1198,11 @@ long mio_tell (MIO *mio)
|
||||
|
||||
return rv;
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertNotReached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -939,13 +1217,15 @@ void mio_rewind (MIO *mio)
|
||||
{
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
rewind (mio->impl.file.fp);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
{
|
||||
mio->impl.mem.pos = 0;
|
||||
mio->impl.mem.ungetch = EOF;
|
||||
mio->impl.mem.eof = false;
|
||||
mio->impl.mem.error = false;
|
||||
}
|
||||
else
|
||||
AssertNotReached ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -967,7 +1247,7 @@ int mio_getpos (MIO *mio, MIOPos *pos)
|
||||
pos->type = mio->type;
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
rv = fgetpos (mio->impl.file.fp, &pos->impl.file);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
{
|
||||
rv = -1;
|
||||
|
||||
@ -984,6 +1264,9 @@ int mio_getpos (MIO *mio, MIOPos *pos)
|
||||
rv = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
AssertNotReached();
|
||||
|
||||
#ifdef MIO_DEBUG
|
||||
if (rv != -1)
|
||||
{
|
||||
@ -1028,7 +1311,7 @@ int mio_setpos (MIO *mio, MIOPos *pos)
|
||||
|
||||
if (mio->type == MIO_TYPE_FILE)
|
||||
rv = fsetpos (mio->impl.file.fp, &pos->impl.file);
|
||||
else
|
||||
else if (mio->type == MIO_TYPE_MEMORY)
|
||||
{
|
||||
rv = -1;
|
||||
|
||||
@ -1041,6 +1324,8 @@ int mio_setpos (MIO *mio, MIOPos *pos)
|
||||
rv = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
AssertNotReached ();
|
||||
|
||||
return rv;
|
||||
}
|
||||
@ -1061,3 +1346,38 @@ int mio_flush (MIO *mio)
|
||||
return fflush (mio->impl.file.fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* mio_attach_user_data:
|
||||
* @mio: A #MIO object
|
||||
* @user_data: a pointer to any data object
|
||||
* @user_data_free_func: a call back function to destroy the data object passed as @user_data
|
||||
*
|
||||
* Attach any data object to a #MIO object. Attached data can be got with
|
||||
* mio_get_user_data(). The attached data is destroyed when new data is attached to
|
||||
* the #MIO object, or #the MIO object itself is destroyed. For destroying the data
|
||||
* @user_data_free_func is used.
|
||||
*
|
||||
*/
|
||||
|
||||
void mio_attach_user_data (MIO *mio, void *user_data, MIODestroyNotify user_data_free_func)
|
||||
{
|
||||
if (mio->udata.d && mio->udata.f)
|
||||
mio->udata.f (mio->udata.d);
|
||||
|
||||
mio->udata.d = user_data;
|
||||
mio->udata.f = user_data_free_func;
|
||||
}
|
||||
|
||||
/**
|
||||
* mio_get_user_data:
|
||||
* @mio: A #MIO object
|
||||
*
|
||||
* Returns: user data attached with mio_attach_user_data() to a #MIO object.
|
||||
*
|
||||
*/
|
||||
void *mio_get_user_data (MIO *mio)
|
||||
{
|
||||
return mio->udata.d;
|
||||
}
|
||||
|
@ -21,7 +21,11 @@
|
||||
#ifndef MIO_H
|
||||
#define MIO_H
|
||||
|
||||
#ifndef QUALIFIER
|
||||
#include "general.h" /* must always come first */
|
||||
#else
|
||||
#include "gcc-attr.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
@ -96,7 +100,7 @@ typedef void (*MIODestroyNotify) (void *data);
|
||||
*/
|
||||
struct _MIOPos {
|
||||
/*< private >*/
|
||||
unsigned int type;
|
||||
MIOType type;
|
||||
#ifdef MIO_DEBUG
|
||||
void *tag;
|
||||
#endif
|
||||
@ -106,33 +110,6 @@ struct _MIOPos {
|
||||
} impl;
|
||||
};
|
||||
|
||||
/**
|
||||
* MIO:
|
||||
*
|
||||
* An object representing a #MIO stream. No assumptions should be made about
|
||||
* what compose this object, and none of its fields should be accessed directly.
|
||||
*/
|
||||
struct _MIO {
|
||||
/*< private >*/
|
||||
unsigned int type;
|
||||
union {
|
||||
struct {
|
||||
FILE *fp;
|
||||
MIOFCloseFunc close_func;
|
||||
} file;
|
||||
struct {
|
||||
unsigned char *buf;
|
||||
int ungetch;
|
||||
size_t pos;
|
||||
size_t size;
|
||||
size_t allocated_size;
|
||||
MIOReallocFunc realloc_func;
|
||||
MIODestroyNotify free_func;
|
||||
bool error;
|
||||
bool eof;
|
||||
} mem;
|
||||
} impl;
|
||||
};
|
||||
|
||||
|
||||
MIO *mio_new_file (const char *filename, const char *mode);
|
||||
@ -145,6 +122,10 @@ MIO *mio_new_memory (unsigned char *data,
|
||||
size_t size,
|
||||
MIOReallocFunc realloc_func,
|
||||
MIODestroyNotify free_func);
|
||||
|
||||
MIO *mio_new_mio (MIO *base, long start, size_t size);
|
||||
MIO *mio_ref (MIO *mio);
|
||||
|
||||
int mio_free (MIO *mio);
|
||||
FILE *mio_file_get_fp (MIO *mio);
|
||||
unsigned char *mio_memory_get_data (MIO *mio, size_t *size);
|
||||
@ -175,4 +156,7 @@ int mio_getpos (MIO *mio, MIOPos *pos);
|
||||
int mio_setpos (MIO *mio, MIOPos *pos);
|
||||
int mio_flush (MIO *mio);
|
||||
|
||||
void mio_attach_user_data (MIO *mio, void *user_data, MIODestroyNotify user_data_free_func);
|
||||
void *mio_get_user_data (MIO *mio);
|
||||
|
||||
#endif /* MIO_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user