basic ios read, write, and stream creation
This commit is contained in:
parent
fa0e134dd8
commit
755bb33714
|
@ -31,7 +31,7 @@ release: $(OBJS)
|
||||||
|
|
||||||
test:
|
test:
|
||||||
make clean
|
make clean
|
||||||
make release CFLAGS=-DENABLE_LLT_TEST
|
make debug CFLAGS=-DENABLE_LLT_TEST
|
||||||
gcc $(TESTSRC) $(TARGET) -o $(TESTER) -lm
|
gcc $(TESTSRC) $(TARGET) -o $(TESTER) -lm
|
||||||
./$(TESTER)
|
./$(TESTER)
|
||||||
|
|
||||||
|
|
|
@ -46,14 +46,14 @@ void snprint_cplx(char *s, size_t cnt, double re, double im,
|
||||||
if (!fzi) {
|
if (!fzi) {
|
||||||
len = sl = strlen(s);
|
len = sl = strlen(s);
|
||||||
if (dbl_equals(im, -1)) {
|
if (dbl_equals(im, -1)) {
|
||||||
while (len-sl < (size_t)width-2 && len < (space-3))
|
while ((long)(len-sl) < (long)(width-2) && len < (space-3))
|
||||||
s[len++] = ' ';
|
s[len++] = ' ';
|
||||||
s[len] = '-';
|
s[len] = '-';
|
||||||
s[len+1] = 'i';
|
s[len+1] = 'i';
|
||||||
s[len+2] = '\0';
|
s[len+2] = '\0';
|
||||||
}
|
}
|
||||||
else if (dbl_equals(im, 1)) {
|
else if (dbl_equals(im, 1)) {
|
||||||
while (len-sl < (size_t)width-1 && len < (space-2))
|
while ((long)(len-sl) < (long)(width-1) && len < (space-2))
|
||||||
s[len++] = ' ';
|
s[len++] = ' ';
|
||||||
s[len] = 'i';
|
s[len] = 'i';
|
||||||
s[len+1] = '\0';
|
s[len+1] = '\0';
|
||||||
|
|
173
llt/ios.c
173
llt/ios.c
|
@ -5,6 +5,7 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
#include <stdio.h> // for printf
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
@ -15,6 +16,8 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "dtypes.h"
|
#include "dtypes.h"
|
||||||
|
@ -223,7 +226,7 @@ static size_t _writebuf_force(ios_t *s, char *data, size_t n)
|
||||||
|
|
||||||
/* interface functions, low level */
|
/* interface functions, low level */
|
||||||
|
|
||||||
size_t ios_read(ios_t *s, char *dest, size_t n, int all)
|
static size_t _ios_read(ios_t *s, char *dest, size_t n, int all)
|
||||||
{
|
{
|
||||||
size_t tot = 0;
|
size_t tot = 0;
|
||||||
size_t got, avail;
|
size_t got, avail;
|
||||||
|
@ -289,12 +292,23 @@ size_t ios_read(ios_t *s, char *dest, size_t n, int all)
|
||||||
return tot;
|
return tot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ios_read(ios_t *s, char *dest, size_t n)
|
||||||
|
{
|
||||||
|
return _ios_read(s, dest, n, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ios_readall(ios_t *s, char *dest, size_t n)
|
||||||
|
{
|
||||||
|
return _ios_read(s, dest, n, 1);
|
||||||
|
}
|
||||||
|
|
||||||
size_t ios_write(ios_t *s, char *data, size_t n)
|
size_t ios_write(ios_t *s, char *data, size_t n)
|
||||||
{
|
{
|
||||||
if (n == 0) return 0;
|
if (n == 0) return 0;
|
||||||
size_t space;
|
size_t space;
|
||||||
size_t wrote = 0;
|
size_t wrote = 0;
|
||||||
|
|
||||||
|
if (s->state == bst_none) s->state = bst_wr;
|
||||||
if (s->state == bst_wr)
|
if (s->state == bst_wr)
|
||||||
space = s->maxsize - s->bpos;
|
space = s->maxsize - s->bpos;
|
||||||
else
|
else
|
||||||
|
@ -308,9 +322,21 @@ size_t ios_write(ios_t *s, char *data, size_t n)
|
||||||
return wrote;
|
return wrote;
|
||||||
}
|
}
|
||||||
else if (n <= space) {
|
else if (n <= space) {
|
||||||
|
if (s->bm == bm_line) {
|
||||||
|
char *nl;
|
||||||
|
if ((nl=(char*)memrchr(data, '\n', n)) != NULL) {
|
||||||
|
size_t linesz = nl-data+1;
|
||||||
|
s->bm = bm_block;
|
||||||
|
wrote += ios_write(s, data, linesz);
|
||||||
|
ios_flush(s);
|
||||||
|
s->bm = bm_line;
|
||||||
|
n -= linesz;
|
||||||
|
data += linesz;
|
||||||
|
}
|
||||||
|
}
|
||||||
memcpy(s->buf + s->bpos, data, n);
|
memcpy(s->buf + s->bpos, data, n);
|
||||||
s->bpos += n;
|
s->bpos += n;
|
||||||
wrote = n;
|
wrote += n;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
s->state = bst_wr;
|
s->state = bst_wr;
|
||||||
|
@ -331,6 +357,13 @@ size_t ios_write(ios_t *s, char *data, size_t n)
|
||||||
off_t ios_seek(ios_t *s, off_t pos)
|
off_t ios_seek(ios_t *s, off_t pos)
|
||||||
{
|
{
|
||||||
s->_eof = 0;
|
s->_eof = 0;
|
||||||
|
if (s->bm == bm_mem) {
|
||||||
|
if ((size_t)pos > s->size)
|
||||||
|
return -1;
|
||||||
|
s->bpos = pos;
|
||||||
|
return s->bpos;
|
||||||
|
}
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t ios_seek_end(ios_t *s)
|
off_t ios_seek_end(ios_t *s)
|
||||||
|
@ -548,21 +581,155 @@ int ios_copyall(ios_t *to, ios_t *from)
|
||||||
return ios_copy_(to, from, 0, 1);
|
return ios_copy_(to, from, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _ios_init(ios_t *s)
|
||||||
|
{
|
||||||
|
// put all fields in a sane initial state
|
||||||
|
s->bm = bm_block;
|
||||||
|
s->state = bst_none;
|
||||||
|
s->errcode = 0;
|
||||||
|
s->buf = NULL;
|
||||||
|
s->maxsize = 0;
|
||||||
|
s->size = 0;
|
||||||
|
s->bpos = 0;
|
||||||
|
s->ndirty = 0;
|
||||||
|
s->tally = 0;
|
||||||
|
s->fd = -1;
|
||||||
|
s->byteswap = 0;
|
||||||
|
s->ownbuf = 0;
|
||||||
|
s->ownfd = 0;
|
||||||
|
s->_eof = 0;
|
||||||
|
s->rereadable = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* stream object initializers. we do no allocation. */
|
/* stream object initializers. we do no allocation. */
|
||||||
|
|
||||||
ios_t *ios_file(ios_t *s, char *fname, int create, int rewrite)
|
ios_t *ios_file(ios_t *s, char *fname, int create, int rewrite)
|
||||||
{
|
{
|
||||||
|
int fd;
|
||||||
|
int flags = O_RDWR;
|
||||||
|
if (create) flags |= O_CREAT;
|
||||||
|
if (rewrite) flags |= O_TRUNC;
|
||||||
|
fd = open(fname, flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH/*644*/);
|
||||||
|
if (fd == -1) {
|
||||||
|
s->fd = -1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
s = ios_fd(s, fd, 1);
|
||||||
|
s->ownfd = 1;
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
ios_t *ios_mem(ios_t *s, size_t initsize)
|
ios_t *ios_mem(ios_t *s, size_t initsize)
|
||||||
{
|
{
|
||||||
|
_ios_init(s);
|
||||||
|
s->bm = bm_mem;
|
||||||
|
_buf_realloc(s, initsize);
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
ios_t *ios_fd(ios_t *s, long fd)
|
ios_t *ios_str(ios_t *s, char *str)
|
||||||
{
|
{
|
||||||
|
size_t n = strlen(str);
|
||||||
|
if (ios_mem(s, n+1)==NULL) return NULL;
|
||||||
|
ios_write(s, str, n+1);
|
||||||
|
ios_seek(s, 0);
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ios_t *ios_fd(ios_t *s, long fd, int isfile)
|
||||||
|
{
|
||||||
|
_ios_init(s);
|
||||||
|
s->fd = fd;
|
||||||
|
if (isfile) s->rereadable = 1;
|
||||||
|
_buf_init(s, bm_block);
|
||||||
|
s->ownfd = 0;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
ios_t *ios_stdin()
|
||||||
|
{
|
||||||
|
static ios_t *_ios_stdin = NULL;
|
||||||
|
if (_ios_stdin == NULL) {
|
||||||
|
_ios_stdin = malloc(sizeof(ios_t));
|
||||||
|
ios_fd(_ios_stdin, STDIN_FILENO, 0);
|
||||||
|
}
|
||||||
|
return _ios_stdin;
|
||||||
|
}
|
||||||
|
|
||||||
|
ios_t *ios_stdout()
|
||||||
|
{
|
||||||
|
static ios_t *_ios_stdout = NULL;
|
||||||
|
if (_ios_stdout == NULL) {
|
||||||
|
_ios_stdout = malloc(sizeof(ios_t));
|
||||||
|
ios_fd(_ios_stdout, STDOUT_FILENO, 0);
|
||||||
|
_ios_stdout->bm = bm_line;
|
||||||
|
}
|
||||||
|
return _ios_stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
ios_t *ios_stderr()
|
||||||
|
{
|
||||||
|
static ios_t *_ios_stderr = NULL;
|
||||||
|
if (_ios_stderr == NULL) {
|
||||||
|
_ios_stderr = malloc(sizeof(ios_t));
|
||||||
|
ios_fd(_ios_stderr, STDERR_FILENO, 0);
|
||||||
|
_ios_stderr->bm = bm_none;
|
||||||
|
}
|
||||||
|
return _ios_stderr;
|
||||||
|
}
|
||||||
|
|
||||||
/* higher level interface */
|
/* higher level interface */
|
||||||
|
|
||||||
|
int ios_putc(int c, ios_t *s)
|
||||||
|
{
|
||||||
|
char ch = (char)c;
|
||||||
|
|
||||||
|
return (int)ios_write(s, &ch, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ios_getc(ios_t *s)
|
||||||
|
{
|
||||||
|
if (s->_eof) return IOS_EOF;
|
||||||
|
char ch;
|
||||||
|
size_t n = ios_read(s, &ch, 1);
|
||||||
|
if (n < 1)
|
||||||
|
return IOS_EOF;
|
||||||
|
return (int)ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ios_ungetc(int c, ios_t *s)
|
||||||
|
{
|
||||||
|
if (s->state == bst_wr)
|
||||||
|
return IOS_EOF;
|
||||||
|
if (s->bpos > 0) {
|
||||||
|
s->bpos--;
|
||||||
|
s->buf[s->bpos] = (char)c;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
if (s->size == s->maxsize) {
|
||||||
|
if (_buf_realloc(s, s->maxsize*2) == NULL)
|
||||||
|
return IOS_EOF;
|
||||||
|
}
|
||||||
|
memmove(s->buf + 1, s->buf, s->size);
|
||||||
|
s->buf[0] = (char)c;
|
||||||
|
s->size++;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ios_printf(ios_t *s, char *format, ...)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
// TODO: avoid copy
|
||||||
|
int c = vasprintf(&str, format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (c == -1) return c;
|
||||||
|
|
||||||
|
ios_write(s, str, c);
|
||||||
|
|
||||||
|
free(str);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
26
llt/ios.h
26
llt/ios.h
|
@ -61,7 +61,8 @@ typedef struct {
|
||||||
} ios_t;
|
} ios_t;
|
||||||
|
|
||||||
/* low-level interface functions */
|
/* low-level interface functions */
|
||||||
size_t ios_read(ios_t *s, char *dest, size_t n, int all);
|
size_t ios_read(ios_t *s, char *dest, size_t n);
|
||||||
|
size_t ios_readall(ios_t *s, char *dest, size_t n);
|
||||||
size_t ios_write(ios_t *s, char *data, size_t n);
|
size_t ios_write(ios_t *s, char *data, size_t n);
|
||||||
off_t ios_seek(ios_t *s, off_t pos); // absolute seek
|
off_t ios_seek(ios_t *s, off_t pos); // absolute seek
|
||||||
off_t ios_seek_end(ios_t *s);
|
off_t ios_seek_end(ios_t *s);
|
||||||
|
@ -87,8 +88,12 @@ int ios_copyall(ios_t *to, ios_t *from);
|
||||||
/* stream creation */
|
/* stream creation */
|
||||||
ios_t *ios_file(ios_t *s, char *fname, int create, int rewrite);
|
ios_t *ios_file(ios_t *s, char *fname, int create, int rewrite);
|
||||||
ios_t *ios_mem(ios_t *s, size_t initsize);
|
ios_t *ios_mem(ios_t *s, size_t initsize);
|
||||||
ios_t *ios_fd(ios_t *s, long fd);
|
ios_t *ios_str(ios_t *s, char *str);
|
||||||
|
ios_t *ios_fd(ios_t *s, long fd, int isfile);
|
||||||
// todo: ios_socket
|
// todo: ios_socket
|
||||||
|
ios_t *ios_stdin();
|
||||||
|
ios_t *ios_stdout();
|
||||||
|
ios_t *ios_stderr();
|
||||||
|
|
||||||
/* high-level functions - output */
|
/* high-level functions - output */
|
||||||
int ios_putnum(ios_t *s, char *data, uint32_t type);
|
int ios_putnum(ios_t *s, char *data, uint32_t type);
|
||||||
|
@ -112,13 +117,13 @@ int ios_prevutf8(ios_t *s);
|
||||||
|
|
||||||
/* stdio-style functions */
|
/* stdio-style functions */
|
||||||
#define IOS_EOF (-1)
|
#define IOS_EOF (-1)
|
||||||
int ios_putc(ios_t *s, int c);
|
int ios_putc(int c, ios_t *s);
|
||||||
//wint_t ios_putwc(ios_t *s, wchar_t wc);
|
//wint_t ios_putwc(ios_t *s, wchar_t wc);
|
||||||
int ios_getc(ios_t *s);
|
int ios_getc(ios_t *s);
|
||||||
//wint_t ios_getwc(ios_t *s);
|
//wint_t ios_getwc(ios_t *s);
|
||||||
int ios_ungetc(ios_t *s, int c);
|
int ios_ungetc(int c, ios_t *s);
|
||||||
//wint_t ios_ungetwc(ios_t *s, wint_t wc);
|
//wint_t ios_ungetwc(ios_t *s, wint_t wc);
|
||||||
#define ios_puts(s, str) ios_write(s, str, strlen(str))
|
#define ios_puts(str, s) ios_write(s, str, strlen(str))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
With memory streams, mixed reads and writes are equivalent to performing
|
With memory streams, mixed reads and writes are equivalent to performing
|
||||||
|
@ -164,21 +169,18 @@ int ios_ungetc(ios_t *s, int c);
|
||||||
|
|
||||||
design points:
|
design points:
|
||||||
- data-source independence, including memory streams
|
- data-source independence, including memory streams
|
||||||
- support 64-bit and large files
|
|
||||||
- efficient, low-latency buffering
|
|
||||||
- unget
|
|
||||||
- expose buffer to user, allow user-owned buffers
|
- expose buffer to user, allow user-owned buffers
|
||||||
- allow direct I/O, don't always go through buffer
|
- allow direct I/O, don't always go through buffer
|
||||||
- buffer-internal seeking. makes seeking back 1-2 bytes very fast,
|
- buffer-internal seeking. makes seeking back 1-2 bytes very fast,
|
||||||
and makes it possible for sockets where it otherwise wouldn't be
|
and makes it possible for sockets where it otherwise wouldn't be
|
||||||
- special support for utf8
|
|
||||||
- tries to allow switching between reading and writing
|
- tries to allow switching between reading and writing
|
||||||
|
- support 64-bit and large files
|
||||||
|
- efficient, low-latency buffering
|
||||||
|
- special support for utf8
|
||||||
- type-aware functions with byte-order swapping service
|
- type-aware functions with byte-order swapping service
|
||||||
- position counter for meaningful data offsets with sockets
|
- position counter for meaningful data offsets with sockets
|
||||||
|
|
||||||
note:
|
theory of operation:
|
||||||
the current code needs to be mostly rewritten. the design should be
|
|
||||||
as follows:
|
|
||||||
|
|
||||||
the buffer is a view of part of a file/stream. you can seek, read, and
|
the buffer is a view of part of a file/stream. you can seek, read, and
|
||||||
write around in it as much as you like, as if it were just a string.
|
write around in it as much as you like, as if it were just a string.
|
||||||
|
|
|
@ -43,6 +43,8 @@ int main()
|
||||||
printf("u8 took %.4f sec (%d)\n\n", clock_now()-t0, j);
|
printf("u8 took %.4f sec (%d)\n\n", clock_now()-t0, j);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
test_ios();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,3 +113,32 @@ void test_dblprint()
|
||||||
|
|
||||||
prettyreal(DBL_EPSILON);
|
prettyreal(DBL_EPSILON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_ios()
|
||||||
|
{
|
||||||
|
ios_t *out = ios_stdout();
|
||||||
|
ios_t *in = ios_stdin();
|
||||||
|
|
||||||
|
ios_putc('a', out);
|
||||||
|
ios_putc('b', out);
|
||||||
|
ios_putc('\n', out);
|
||||||
|
|
||||||
|
char c[80];
|
||||||
|
size_t i=0;
|
||||||
|
ios_t sts;
|
||||||
|
ios_str(&sts, "Test string.");
|
||||||
|
c[i++] = ios_getc(&sts);
|
||||||
|
c[i++] = ios_getc(&sts);
|
||||||
|
c[i++] = ios_getc(&sts);
|
||||||
|
c[i++] = '\0';
|
||||||
|
printf("got: \"%s\"\n", c);
|
||||||
|
|
||||||
|
ios_t ms;
|
||||||
|
ios_mem(&ms, 10);
|
||||||
|
int j;
|
||||||
|
for(j=0; j < 16; j++)
|
||||||
|
ios_puts("passersby were amazed by the ", &ms);
|
||||||
|
size_t bs;
|
||||||
|
char *bigstr = ios_takebuf(&ms, &bs);
|
||||||
|
printf("got: \"%s\" (size %d)\n", bigstr, bs);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue