forked from Telodendria/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
|
||||
-----------------
|
||||
|
||||
[ ] Stream API
|
||||
[~] Stream API
|
||||
[~] Implementation
|
||||
[ ] Convert all HTTP code and JSON code
|
||||
[ ] Multi-output (proof of concept)
|
||||
[ ] TLS
|
||||
[ ] SOCKS
|
||||
[ ] Multi-output
|
||||
[ ] Move UtilStreamCopy()
|
||||
[ ] Move/convert UtilStreamCopy()
|
||||
[~] HTTP Client API
|
||||
[x] Document HttpParseHeaders()
|
||||
[ ] 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