Commit f0a72fde authored by Julian Kranz's avatar Julian Kranz

Memstream

parent f165dc25
#ifndef MEMSTREAM_H_
#define MEMSTREAM_H_
#include <stdio.h>
extern FILE *open_memstream(char **cp, size_t *lenp);
#endif /* MEMSTREAM_H_ */
/* Use funopen(3) to provide open_memstream(3) like functionality. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
struct memstream {
char **cp;
size_t *lenp;
size_t offset;
};
static void memstream_grow(struct memstream *ms, size_t newsize) {
char *buf;
if(newsize > *ms->lenp) {
buf = realloc(*ms->cp, newsize + 1);
if(buf != NULL) {
#ifdef DEBUG
fprintf(stderr, "MS: %p growing from %zd to %zd\n",
ms, *ms->lenp, newsize);
#endif
memset(buf + *ms->lenp + 1, 0, newsize - *ms->lenp);
*ms->cp = buf;
*ms->lenp = newsize;
}
}
}
static int memstream_read(void *cookie, char *buf, int len) {
struct memstream *ms;
int tocopy;
ms = cookie;
memstream_grow(ms, ms->offset + len);
tocopy = *ms->lenp - ms->offset;
if(len < tocopy)
tocopy = len;
memcpy(buf, *ms->cp + ms->offset, tocopy);
ms->offset += tocopy;
#ifdef DEBUG
fprintf(stderr, "MS: read(%p, %d) = %d\n", ms, len, tocopy);
#endif
return (tocopy);
}
static int memstream_write(void *cookie, const char *buf, int len) {
struct memstream *ms;
int tocopy;
ms = cookie;
memstream_grow(ms, ms->offset + len);
tocopy = *ms->lenp - ms->offset;
if(len < tocopy)
tocopy = len;
memcpy(*ms->cp + ms->offset, buf, tocopy);
ms->offset += tocopy;
#ifdef DEBUG
fprintf(stderr, "MS: write(%p, %d) = %d\n", ms, len, tocopy);
#endif
return (tocopy);
}
static fpos_t memstream_seek(void *cookie, fpos_t pos, int whence) {
struct memstream *ms;
#ifdef DEBUG
size_t old;
#endif
ms = cookie;
#ifdef DEBUG
old = ms->offset;
#endif
switch(whence) {
case SEEK_SET:
ms->offset = pos;
break;
case SEEK_CUR:
ms->offset += pos;
break;
case SEEK_END:
ms->offset = *ms->lenp + pos;
break;
}
#ifdef DEBUG
fprintf(stderr, "MS: seek(%p, %zd, %d) %zd -> %zd\n", ms, pos, whence,
old, ms->offset);
#endif
return (ms->offset);
}
static int memstream_close(void *cookie) {
free(cookie);
return (0);
}
FILE *
open_memstream(char **cp, size_t *lenp) {
struct memstream *ms;
int save_errno;
FILE *fp;
*cp = NULL;
*lenp = 0;
ms = malloc(sizeof(*ms));
ms->cp = cp;
ms->lenp = lenp;
ms->offset = 0;
fp = funopen(ms, memstream_read, memstream_write, memstream_seek, memstream_close);
if(fp == NULL) {
save_errno = errno;
free(ms);
errno = save_errno;
}
return (fp);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment