forked from lda/telodendria
Begin prototyping Stream API.
This commit is contained in:
parent
ae97d8116c
commit
afc7667737
3 changed files with 248 additions and 3 deletions
8
TODO.txt
8
TODO.txt
|
@ -11,11 +11,13 @@ Key:
|
||||||
Milestone: v0.3.0
|
Milestone: v0.3.0
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
[ ] Stream API
|
[~] Stream API
|
||||||
|
[~] Implementation
|
||||||
|
[ ] Convert all HTTP code and JSON code
|
||||||
|
[ ] Multi-output (proof of concept)
|
||||||
[ ] TLS
|
[ ] TLS
|
||||||
[ ] SOCKS
|
[ ] SOCKS
|
||||||
[ ] Multi-output
|
[ ] Move/convert UtilStreamCopy()
|
||||||
[ ] Move UtilStreamCopy()
|
|
||||||
[~] HTTP Client API
|
[~] HTTP Client API
|
||||||
[x] Document HttpParseHeaders()
|
[x] Document HttpParseHeaders()
|
||||||
[ ] HttpClient man page
|
[ ] HttpClient man page
|
||||||
|
|
170
src/Stream.c
Normal file
170
src/Stream.c
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
#include <Stream.h>
|
||||||
|
|
||||||
|
#include <Memory.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
struct Stream
|
||||||
|
{
|
||||||
|
StreamFunctions io;
|
||||||
|
void *cookie;
|
||||||
|
|
||||||
|
int *ub;
|
||||||
|
size_t ubSize;
|
||||||
|
size_t ubLen;
|
||||||
|
};
|
||||||
|
|
||||||
|
Stream *
|
||||||
|
StreamCreate(void *cookie, StreamFunctions funcs)
|
||||||
|
{
|
||||||
|
Stream *stream;
|
||||||
|
|
||||||
|
if (!funcs.read || !funcs.write)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream = Malloc(sizeof(Stream));
|
||||||
|
|
||||||
|
if (!stream)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->cookie = cookie;
|
||||||
|
|
||||||
|
stream->io.read = funcs.read;
|
||||||
|
stream->io.write = funcs.write;
|
||||||
|
stream->io.seek = funcs.seek;
|
||||||
|
stream->io.close = funcs.close;
|
||||||
|
|
||||||
|
stream->ubSize = 0;
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
StreamRead(Stream *stream, void *buf, size_t nBytes)
|
||||||
|
{
|
||||||
|
if (!stream)
|
||||||
|
{
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream->io.read(stream->cookie, buf, nBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
StreamWrite(Stream *stream, void *buf, size_t nBytes)
|
||||||
|
{
|
||||||
|
if (!stream)
|
||||||
|
{
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream->io.write(stream->cookie, buf, nBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t
|
||||||
|
StreamSeek(Stream *stream, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
if (!stream)
|
||||||
|
{
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stream->io.seek)
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream->io.seek(stream->cookie, offset, whence);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
StreamClose(Stream *stream)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!stream)
|
||||||
|
{
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream->io.close)
|
||||||
|
{
|
||||||
|
ret = stream->io.close(stream->cookie);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream->ubSize)
|
||||||
|
{
|
||||||
|
Free(stream->ub);
|
||||||
|
}
|
||||||
|
|
||||||
|
Free(stream);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
StreamReadFd(void *cookie, void *buf, size_t nBytes)
|
||||||
|
{
|
||||||
|
int fd = *((int *) cookie);
|
||||||
|
|
||||||
|
return read(fd, buf, nBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
StreamWriteFd(void *cookie, void *buf, size_t nBytes)
|
||||||
|
{
|
||||||
|
int fd = *((int *) cookie);
|
||||||
|
|
||||||
|
return write(fd, buf, nBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static off_t
|
||||||
|
StreamSeekFd(void *cookie, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
int fd = *((int *) cookie);
|
||||||
|
|
||||||
|
return lseek(fd, offset, whence);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
StreamCloseFd(void *cookie)
|
||||||
|
{
|
||||||
|
int fd = *((int *) cookie);
|
||||||
|
|
||||||
|
return close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream *
|
||||||
|
StreamOpen(int fd)
|
||||||
|
{
|
||||||
|
int *fdp = Malloc(sizeof(int));
|
||||||
|
StreamFunctions f;
|
||||||
|
|
||||||
|
if (!fdp)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*fdp = fd;
|
||||||
|
|
||||||
|
f.read = StreamReadFd;
|
||||||
|
f.write = StreamWriteFd;
|
||||||
|
f.seek = StreamSeekFd;
|
||||||
|
f.close = StreamCloseFd;
|
||||||
|
|
||||||
|
return StreamCreate(fdp, f);
|
||||||
|
|
||||||
|
}
|
73
src/include/Stream.h
Normal file
73
src/include/Stream.h
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
#ifndef TELODENDRIA_STREAM_H
|
||||||
|
#define TELODENDRIA_STREAM_H
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
typedef struct Stream Stream;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Low-level Stream API in the style of POSIX system calls.
|
||||||
|
* Heavily inspired by GNU fopencookie() and BSD funopen().
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef ssize_t (StreamReadFunc) (void *, void *, size_t);
|
||||||
|
typedef ssize_t (StreamWriteFunc) (void *, void *, size_t);
|
||||||
|
typedef off_t (StreamSeekFunc) (void *, off_t, int);
|
||||||
|
typedef int (StreamCloseFunc) (void *);
|
||||||
|
|
||||||
|
typedef struct StreamFunctions
|
||||||
|
{
|
||||||
|
StreamReadFunc *read;
|
||||||
|
StreamWriteFunc *write;
|
||||||
|
StreamSeekFunc *seek;
|
||||||
|
StreamCloseFunc *close;
|
||||||
|
} StreamFunctions;
|
||||||
|
|
||||||
|
extern Stream *
|
||||||
|
StreamCreate(void *, StreamFunctions);
|
||||||
|
|
||||||
|
extern ssize_t
|
||||||
|
StreamRead(Stream *, void *, size_t);
|
||||||
|
|
||||||
|
extern ssize_t
|
||||||
|
StreamWrite(Stream *, void *, size_t);
|
||||||
|
|
||||||
|
extern off_t
|
||||||
|
StreamSeek(Stream *, off_t, int);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
StreamClose(Stream *);
|
||||||
|
|
||||||
|
extern Stream *
|
||||||
|
StreamOpen(int);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* High level Stream API in the style of C standard I/O.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int
|
||||||
|
StreamVprintf(Stream *, const char *, va_list);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
StreamPrintf(Stream *, const char *, ...);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
StreamGetc(Stream *);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
StreamUngetc(Stream *, int);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
StreamEof(Stream *);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
StreamError(Stream *);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
StreamClearError(Stream *);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
StreamFlush(Stream *);
|
||||||
|
|
||||||
|
#endif /* TELODENDRIA_STREAM_H */
|
Loading…
Reference in a new issue