basic ios read, write, and stream creation
This commit is contained in:
parent
fa0e134dd8
commit
755bb33714
|
@ -31,7 +31,7 @@ release: $(OBJS)
|
|||
|
||||
test:
|
||||
make clean
|
||||
make release CFLAGS=-DENABLE_LLT_TEST
|
||||
make debug CFLAGS=-DENABLE_LLT_TEST
|
||||
gcc $(TESTSRC) $(TARGET) -o $(TESTER) -lm
|
||||
./$(TESTER)
|
||||
|
||||
|
|
|
@ -46,14 +46,14 @@ void snprint_cplx(char *s, size_t cnt, double re, double im,
|
|||
if (!fzi) {
|
||||
len = sl = strlen(s);
|
||||
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+1] = 'i';
|
||||
s[len+2] = '\0';
|
||||
}
|
||||
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] = 'i';
|
||||
s[len+1] = '\0';
|
||||
|
|
173
llt/ios.c
173
llt/ios.c
|
@ -5,6 +5,7 @@
|
|||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <wchar.h>
|
||||
#include <stdio.h> // for printf
|
||||
|
||||
#ifdef WIN32
|
||||
#include <malloc.h>
|
||||
|
@ -15,6 +16,8 @@
|
|||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "dtypes.h"
|
||||
|
@ -223,7 +226,7 @@ static size_t _writebuf_force(ios_t *s, char *data, size_t n)
|
|||
|
||||
/* 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 got, avail;
|
||||
|
@ -289,12 +292,23 @@ size_t ios_read(ios_t *s, char *dest, size_t n, int all)
|
|||
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)
|
||||
{
|
||||
if (n == 0) return 0;
|
||||
size_t space;
|
||||
size_t wrote = 0;
|
||||
|
||||
if (s->state == bst_none) s->state = bst_wr;
|
||||
if (s->state == bst_wr)
|
||||
space = s->maxsize - s->bpos;
|
||||
else
|
||||
|
@ -308,9 +322,21 @@ size_t ios_write(ios_t *s, char *data, size_t n)
|
|||
return wrote;
|
||||
}
|
||||
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);
|
||||
s->bpos += n;
|
||||
wrote = n;
|
||||
wrote += n;
|
||||
}
|
||||
else {
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
@ -548,21 +581,155 @@ int ios_copyall(ios_t *to, ios_t *from)
|
|||
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. */
|
||||
|
||||
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_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 */
|
||||
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
off_t ios_seek(ios_t *s, off_t pos); // absolute seek
|
||||
off_t ios_seek_end(ios_t *s);
|
||||
|
@ -87,8 +88,12 @@ int ios_copyall(ios_t *to, ios_t *from);
|
|||
/* stream creation */
|
||||
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_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
|
||||
ios_t *ios_stdin();
|
||||
ios_t *ios_stdout();
|
||||
ios_t *ios_stderr();
|
||||
|
||||
/* high-level functions - output */
|
||||
int ios_putnum(ios_t *s, char *data, uint32_t type);
|
||||
|
@ -112,13 +117,13 @@ int ios_prevutf8(ios_t *s);
|
|||
|
||||
/* stdio-style functions */
|
||||
#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);
|
||||
int ios_getc(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);
|
||||
#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
|
||||
|
@ -164,21 +169,18 @@ int ios_ungetc(ios_t *s, int c);
|
|||
|
||||
design points:
|
||||
- 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
|
||||
- allow direct I/O, don't always go through buffer
|
||||
- buffer-internal seeking. makes seeking back 1-2 bytes very fast,
|
||||
and makes it possible for sockets where it otherwise wouldn't be
|
||||
- special support for utf8
|
||||
- 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
|
||||
- position counter for meaningful data offsets with sockets
|
||||
|
||||
note:
|
||||
the current code needs to be mostly rewritten. the design should be
|
||||
as follows:
|
||||
theory of operation:
|
||||
|
||||
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.
|
||||
|
|
|
@ -43,6 +43,8 @@ int main()
|
|||
printf("u8 took %.4f sec (%d)\n\n", clock_now()-t0, j);
|
||||
*/
|
||||
|
||||
test_ios();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -111,3 +113,32 @@ void test_dblprint()
|
|||
|
||||
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