diff --git a/llt/Makefile b/llt/Makefile index 64d9a43..afcc7e3 100644 --- a/llt/Makefile +++ b/llt/Makefile @@ -2,7 +2,7 @@ CC = gcc SRCS = bitvector.c hashing.c socket.c timefuncs.c ptrhash.c utf8.c ios.c \ dirpath.c htable.c bitvector-ops.c int2str.c dump.c random.c \ - lltinit.c arraylist.c + lltinit.c OBJS = $(SRCS:%.c=%.o) DOBJS = $(SRCS:%.c=%.do) TARGET = libllt.a diff --git a/llt/Makefile.macosx b/llt/Makefile.macosx index 814830b..5fb5353 100644 --- a/llt/Makefile.macosx +++ b/llt/Makefile.macosx @@ -2,7 +2,7 @@ CC = gcc SRCS = bitvector.c hashing.c socket.c timefuncs.c ptrhash.c utf8.c ios.c \ dirpath.c htable.c bitvector-ops.c int2str.c dump.c random.c \ - lltinit.c arraylist.c + lltinit.c OBJS = $(SRCS:%.c=%.o) DOBJS = $(SRCS:%.c=%.do) TARGET = libllt.a diff --git a/llt/arraylist.c b/llt/arraylist.c deleted file mode 100644 index f58bf4f..0000000 --- a/llt/arraylist.c +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include -#include -#include -#include - -#include "dtypes.h" -#include "arraylist.h" - -arraylist_t *arraylist_new(arraylist_t *a, size_t size) -{ - a->len = 0; - if (size <= AL_N_INLINE) { - a->items = &a->_space[0]; - a->max = AL_N_INLINE; - } - else { - a->items = (void**)LLT_ALLOC(size*sizeof(void*)); - a->max = size; - } - if (a->items == NULL) return NULL; - return a; -} - -void arraylist_free(arraylist_t *a) -{ - if (a->items != &a->_space[0]) - LLT_FREE(a->items); - a->len = 0; - a->max = AL_N_INLINE; - a->items = &a->_space[0]; -} - -static void al_grow(arraylist_t *a, size_t n) -{ - if (a->len+n > a->max) { - if (a->items == &a->_space[0]) { - void **p = LLT_ALLOC((a->len+n)*sizeof(void*)); - if (p == NULL) return; - memcpy(p, a->items, a->len*sizeof(void*)); - a->items = p; - a->max = a->len+n; - } - else { - size_t nm = a->max*2; - if (nm == 0) nm = 1; - while (a->len+n > nm) nm*=2; - void **p = LLT_REALLOC(a->items, nm*sizeof(void*)); - if (p == NULL) return; - a->items = p; - a->max = nm; - } - } - a->len += n; -} - -void arraylist_push(arraylist_t *a, void *elt) -{ - al_grow(a, 1); - a->items[a->len-1] = elt; -} - -void *arraylist_pop(arraylist_t *a) -{ - if (a->len == 0) return NULL; - void *p = a->items[--a->len]; - a->items[a->len] = NULL; - return p; -} diff --git a/llt/arraylist.h b/llt/arraylist.h deleted file mode 100644 index b8f4270..0000000 --- a/llt/arraylist.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __ARRAYLIST_H_ -#define __ARRAYLIST_H_ - -#define AL_N_INLINE 29 - -typedef struct { - size_t len; - size_t max; - void **items; - void *_space[AL_N_INLINE]; -} arraylist_t; - -arraylist_t *arraylist_new(arraylist_t *a, size_t size); -void arraylist_free(arraylist_t *a); - -void arraylist_push(arraylist_t *a, void *elt); -void *arraylist_pop(arraylist_t *a); - -#endif diff --git a/llt/attic/ios.c.old b/llt/attic/ios.c.old deleted file mode 100644 index 5c71a15..0000000 --- a/llt/attic/ios.c.old +++ /dev/null @@ -1,396 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#include -#include -#define fileno _fileno -#else -#include -#include -#include -#endif - -#include "dtypes.h" -#include "utils.h" -#include "utf8.h" -#include "ios.h" -#include "socket.h" - -/* OS-level primitive wrappers */ - -// return error code, #bytes read in *nread -static int _os_read(long fd, void *buf, size_t n, size_t *nread) -{ - ssize_t r = read((int)fd, buf, n); - if (r == -1) { - *nread = 0; - return errno; - } - *nread = (size_t)r; - return 0; -} - -static int _os_write(long fd, void *buf, size_t n, size_t *nwritten) -{ - ssize_t r = write((int)fd, buf, n); - if (r == -1) { - *nwritten = 0; - return errno; - } - *nread = (size_t)r; - return 0; -} - -static int _fd_available(long fd) -{ -#ifndef WIN32 - fd_set set; - struct timeval tv = {0, 0}; - - FD_ZERO(&set); - FD_SET(fd, &set); - return (select(fd+1, &set, NULL, NULL, &tv)!=0); -#else - return 0; -#endif -} - - -/* internal utility functions */ - -static char *_buf_realloc(ios_t *s, size_t sz) -{ - char *temp; - - if (sz <= s->maxsize) - return s->buf; - - if ((s->buf==NULL || s->buf==&s->local[0]) && (sz <= IOS_INLSIZE)) { - /* TODO: if we want to allow shrinking, see if the buffer shrank - down to this size, in which case we need to copy. */ - s->buf = &s->local[0]; - s->maxsize = IOS_INLSIZE; - s->ownbuf = 1; - return s->buf; - } - else if (s->ownbuf && s->buf != &s->local[0]) { - // if we own the buffer we're free to resize it - // always allocate 1 bigger in case user wants to add a NUL - // terminator after taking over the buffer - temp = realloc(s->buf, sz+1); - if (temp == NULL) - return NULL; - } - else { - temp = malloc(sz+1); - s->ownbuf = 1; - if (temp == NULL) - return NULL; - } - - if (s->buf != temp && s->size > 0) - memcpy(temp, s->buf, s->size); - s->buf = temp; - s->maxsize = sz; - return s->buf; -} - -// write a block of data into the buffer at the current position, resizing -// if necessary. returns # written. -static size_t _writebuf_force(ios_t *s, char *data, size_t n) -{ - size_t amt; - size_t newsize; - - if (n == 0) - return 0; - - if (s->bpos + n > s->size) { - if (s->bpos + n > s->maxsize) { - /* TO DO: here you might want to add a mechanism for limiting - the growth of the stream. */ - newsize = s->maxsize * 2; - while (s->bpos + n > newsize) - newsize *= 2; - if (_buf_realloc(s, newsize) == NULL) { - /* no more space; write as much as we can */ - amt = s->maxsize - s->bpos; - if (amt > 0) { - memcpy(&s->buf[s->bpos], data, amt); - } - s->bpos += amt; - s->size = s->maxsize; - return amt; - } - } - s->size = s->bpos + n; - } - memcpy(&s->buf[s->bpos], data, n); - s->bpos += n; - - return n; -} - - -/* interface functions, low level */ - -size_t ios_read(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) -{ -} - -off_t ios_seek_end(ios_t *s) -{ -} - -off_t ios_skip(ios_t *s, off_t offs) -{ -} - -off_t ios_pos(ios_t *s) -{ - if (s->bm == bm_mem) - return (off_t)s->bpos; - - off_t fdpos = lseek(s->fd, 0, SEEK_CUR); - if (fdpos == (off_t)-1) - return fdpos; - - if (s->state == iost_wr) - fdpos += s->bpos; - else if (s->state == iost_rd) - fdpos -= (s->size - s->bpos); - return fdpos; -} - -size_t ios_trunc(ios_t *s, size_t size) -{ -} - -int ios_eof(ios_t *s) -{ - if (s->bm == bm_mem) - return (s->bpos >= s->size); - if (s->fd == -1) - return 1; - // todo -} - -static void _discard_partial_buffer(ios_t *s) -{ - // this function preserves the invariant that data to write - // begins at the beginning of the buffer, and s->size refers - // to how much valid file data is stored in the buffer. - - // this needs to be called when normal operation is interrupted in - // the middle of the buffer. "normal operation" is reading or - // writing to the end of the buffer. this happens e.g. when flushing. - if (s->bpos && s->size > s->bpos) { - memmove(s->buf, s->buf + s->bpos, s->size - s->bpos); - } - s->size -= s->bpos; - s->bpos = 0; -} - -int ios_flush(ios_t *s) -{ - if (ndirty == 0 || s->bm == bm_mem || s->buf == NULL) - return 0; - if (s->fd == -1) - return -1; - - int partialb=0; - if (s->bitpos > 0 && s->ndirty==s->bpos+1) { - // flushing partial byte - partialb=1; - } - - size_t nw, ntowrite=s->ndirty; - int err = _os_write(s->fd, s->buf, ntowrite, &nw); - // todo: try recovering from some kinds of errors (e.g. retry) - if (partialb) { - // skip back 1, since we might have to write this byte again - // if more bits in it are changed - if (lseek(s->fd, -1, SEEK_CUR) == (off_t)-1) { - // uhoh. can't write the "rest" of this byte. move to next - // byte instead. - s->bpos++; - s->bitpos = 0; - } - } - - _discard_partial_buffer(s); - s->ndirty = 0; - - if (err) - return err; - if (nw < ntowrite) - return -1; - return 0; -} - -void ios_close(ios_t *s) -{ - ios_flush(s); - if (s->fd != -1 && s->ownfd) - close(s->fd); - s->fd = -1; -} - -char *ios_takebuf(ios_t *s, size_t *psize) -{ - char *buf; - - ios_flush(s); - - if (s->buf == &s->local[0]) { - buf = malloc(s->size+1); - if (buf == NULL) - return NULL; - if (s->size) - memcpy(buf, s->buf, s->size); - buf[s->size] = '\0'; - } - else { - buf = s->buf; - } - - *psize = s->size+1; // buffer is actually 1 bigger for terminating NUL - - /* empty stream and reinitialize */ - if (s->bm == bm_mem || s->bm == bm_none) { - s->buf = &s->local[0]; - s->maxsize = IOS_INLSIZE; - } - else { - s->buf = NULL; - _buf_realloc(s, IOS_BUFSIZE); - } - s->size = s->bpos = 0; - s->bitpos = 0; - - return buf; -} - -int ios_setbuf(ios_t *s, char *buf, size_t size, int own) -{ - ios_flush(s); - size_t nvalid=0; - - nvalid = s->size; - if (s->size == s->bpos && s->bitpos>0) - nvalid++; - if (size < nvalid) - nvalid = size; - memcpy(buf, s->buf, nvalid); - if (s->bpos > nvalid) { - // truncated - s->bpos = nvalid; - s->bitpos = 0; - } - s->size = nvalid; - - if (s->buf!=NULL && s->ownbuf && s->buf!=&s->local[0]) - free(s->buf); - s->buf = buf; - s->maxsize = size; - s->ownbuf = own; - return 0; -} - -int ios_bufmode(ios_t *s, bufmode_t mode) -{ - // no fd; can only do mem-only buffering - if (s->fd == -1 && mode != bm_mem) - return -1; - s->bm = mode; - return 0; -} - -void ios_bswap(ios_t *s, int bswap) -{ - s->byteswap = !!bswap; -} - -int ios_copy(ios_t *to, ios_t *from, size_t nbytes, bool_t all) -{ -} - - -/* stream object initializers. we do no allocation. */ - -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) -{ -} - - -/* higher level interface */ - -int ios_putbit(ios_t *s, int bit) -{ - byte_t mask = 1<bitpos; - - if (_ios_setstate(s, iost_wr)) - return 0; - - if (!s->dirty) { - // haven't written any bits yet - // if stenciling is turned on, the buffer is already full and - // we don't need to do anything - if (s->rereadable && !s->stenciled) { - // fill buffer if we can - } - } - - if (bit) - s->buf[s->bpos] |= mask; - else - s->buf[s->bpos] &= ~mask; - s->dirty = 1; - - s->bitpos++; - if (s->bitpos > 7) { - s->bitpos = 0; - s->bpos++; - s->tally++; - } - return 1; -} - -int ios_getbit(ios_t *s, int *pbit) -{ - byte_t mask = 1<bitpos; - - if (_ios_setstate(s, iost_rd)) - return 0; - - *pbit = (s->buf[s->bpos] & mask) ? 1 : 0; - s->bitpos++; - if (s->bitpos > 7) { - s->bitpos = 0; - s->bpos++; - s->tally++; - } - return 1; -} diff --git a/llt/attic/ios.h.old b/llt/attic/ios.h.old deleted file mode 100644 index 257b350..0000000 --- a/llt/attic/ios.h.old +++ /dev/null @@ -1,198 +0,0 @@ -#ifndef __IOS_H_ -#define __IOS_H_ - -// this flag controls when data actually moves out to the underlying I/O -// channel. memory streams are a special case of this where the data -// never moves out. -typedef enum { bm_none, bm_line, bm_block, bm_mem } bufmode_t; - -typedef enum { iost_none, iost_rd, iost_wr } iostate_t; - -#define IOS_INLSIZE 54 -#define IOS_BUFSIZE 4095 - -typedef struct { - bufmode_t bm; - - // the state only indicates where the underlying file position is relative - // to the buffer. reading: at the end. writing: at the beginning. - // in general, you can do any operation in any state. - iostate_t state; - - char *buf; // start of buffer - size_t maxsize; // space allocated to buffer - size_t size; // length of valid data in buf, >=ndirty - size_t bpos; // current position in buffer - size_t ndirty; // # bytes at &buf[0] that need to be written - - // this is a public field that keeps a running count of bytes - // read or written. you can freely use and change it. this is - // intended for keeping track of relative positions in streams - // that don't have absolute positions (like sockets). - size_t tally; - - // pointer-size integer to support platforms where it might have - // to be a pointer - long fd; - - byte_t bitpos; - //unsigned char bitdirty:1; // bit buffer needs to be written - unsigned char byteswap:1; - //unsigned char readonly:1; - unsigned char ownbuf:1; - unsigned char ownfd:1; - - // this means you can read, seek back, then read the same data - // again any number of times. usually only true for files and strings. - unsigned char rereadable:1; - - // this enables "stenciled writes". you can alternately write and - // seek without flushing in between. this performs read-before-write - // to populate the buffer, so "rereadable" capability is required. - // this is off by default, except for bit I/O if rereadable is true. - unsigned char stenciled:1; - - // request durable writes (fsync) - // unsigned char durable:1; - - // todo: mutex - char local[IOS_INLSIZE]; -} ios_t; - -/* low-level interface functions */ -size_t ios_read(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); -off_t ios_skip(ios_t *s, off_t offs); // relative seek -off_t ios_pos(ios_t *s); // get current position -size_t ios_trunc(ios_t *s, size_t size); -int ios_eof(ios_t *s); -int ios_flush(ios_t *s); -void ios_close(ios_t *s); -char *ios_takebuf(ios_t *s, size_t *psize); // release buffer to caller -// set buffer space to use -int ios_setbuf(ios_t *s, char *buf, size_t size, int own); -int ios_bufmode(ios_t *s, bufmode_t mode); -void ios_bswap(ios_t *s, int bswap); -int ios_copy(ios_t *to, ios_t *from, size_t nbytes, bool_t all); -//void ios_lock(ios_t *s); -//int ios_trylock(ios_t *s); -//int ios_unlock(ios_t *s); - -/* 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); -// todo: ios_socket - -/* high-level functions - output */ -int ios_putnum(ios_t *s, char *data, uint32_t type); -int ios_putint(ios_t *s, int n); -int ios_pututf8(ios_t *s, uint32_t wc); -int ios_putstringz(ios_t *s, char *str, bool_t do_write_nulterm); -/* single-bit I/O - even works for mixed reads and writes. - mixing bit-level I/O with normal byte stream I/O has undefined effects and - will almost certainly destroy your file. */ -int ios_putbit(ios_t *s, int bit); -int ios_printf(ios_t *s, char *format, ...); - -/* high-level stream functions - input */ -int ios_getnum(ios_t *s, char *data, uint32_t type); -int ios_getutf8(ios_t *s, uint32_t *pwc); -int ios_ungetutf8(ios_t *s, uint32_t wc); -int ios_getstringz(ios_t *dest, ios_t *src); -int ios_getstringn(ios_t *dest, ios_t *src, size_t nchars); -int ios_readline(ios_t *dest, ios_t *s, char delim); -int ios_getline(ios_t *s, char **pbuf, size_t *psz); -int ios_getbit(ios_t *s, int *pbit); // returns # of bits read (0 or 1) - -// seek by utf8 sequence increments -int ios_nextutf8(ios_t *s); -int ios_prevutf8(ios_t *s); - -/* stdio-style functions */ -#define IOS_EOF (-1) -int ios_putc(ios_t *s, int c); -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); -wint_t ios_ungetwc(ios_t *s, wint_t wc); -#define ios_puts(s, str) ios_write(s, str, strlen(str)) - -/* - With memory streams, mixed reads and writes are equivalent to performing - sequences of *p++, as either an lvalue or rvalue. File streams behave - similarly, but other streams might not support this. Using unbuffered - mode makes this more predictable. - - Note on "unget" functions: - There are two kinds of functions here: those that operate on sized - blocks of bytes and those that operate on logical units like "character" - or "integer". The "unget" functions only work on logical units. There - is no "unget n bytes". You can only do an unget after a matching get. - However, data pushed back by an unget is available to all read operations. - The reason for this is that unget is defined in terms of its effect on - the underlying buffer (namely, it rebuffers data as if it had been - buffered but not read yet). IOS reserves the right to perform large block - operations directly, bypassing the buffer. In such a case data was - never buffered, so "rebuffering" has no meaning (i.e. there is no - correspondence between the buffer and the physical stream). - - Single-bit I/O is able to write partial bytes ONLY IF the stream supports - seeking. Also, line buffering is not well-defined in the context of - single-bit I/O, so it might not do what you expect. - - implementation notes: - in order to know where we are in a file, we must ensure the buffer - is only populated from the underlying stream starting with p==buf. - - to switch from writing to reading: flush, set p=buf, cnt=0 - to switch from reading to writing: seek backwards cnt bytes, p=buf, cnt=0 - - when writing: buf starts at curr. physical stream pos, p - buf is how - many bytes we've written logically. cnt==0 - - dirty == (bitpos>0 && state==iost_wr), EXCEPT right after switching from - reading to writing, where we might be in the middle of a byte without - having changed it. - - to write a bit: if !dirty, read up to maxsize-(p-buf) into buffer, then - seek back by the same amount (undo it). write onto those bits. now set - the dirty bit. in this state, we can bit-read up to the end of the byte, - then formally switch to the read state using flush. - - 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 - - single-bit I/O - - tries to allow switching between reading and writing - - 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: - - 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. - - we keep track of the part of the buffer that's invalid (written to). - we remember whether the position of the underlying stream is aligned - with the end of the buffer (reading mode) or the beginning (writing mode). - - based on this info, we might have to seek back before doing a flush. - - as optimizations, we do no writing if the buffer isn't "dirty", and we - do no reading if the data will only be overwritten. -*/ - -#endif diff --git a/llt/attic/streams.c b/llt/attic/streams.c deleted file mode 100644 index 20a7752..0000000 --- a/llt/attic/streams.c +++ /dev/null @@ -1,1107 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#include -#include -#include -#define fileno _fileno -#else -#include -#include -#include -#endif - -#include "dtypes.h" -#include "utils.h" -#include "utf8.h" -#include "streams.h" - -unsigned int type_sizes[] = { - sizeof(int32_t), sizeof(int8_t), sizeof(int16_t), - sizeof(int32_t), sizeof(float), sizeof(double), sizeof(int64_t), 0, - - /* unsigned */ - 0, sizeof(u_int8_t), sizeof(u_int16_t), - sizeof(u_int32_t), 0, 0, sizeof(u_int64_t), 0, - - /* complex */ - 2*sizeof(int32_t), 2*sizeof(int8_t), 2*sizeof(int16_t), - 2*sizeof(int32_t), 2*sizeof(float), 2*sizeof(double), 2*sizeof(int64_t),0, - - /* complex unsigned */ - 0, 2*sizeof(u_int8_t), 2*sizeof(u_int16_t), - 2*sizeof(u_int32_t), 0, 0, 2*sizeof(u_int64_t), 0 -}; - -bool_t valid_type(u_int32_t type) -{ - u_int32_t sz; - - /* irrelevant bits set */ - if (type & ~T_TYPEMASK) - return false; - sz = type & T_TYPESIZE; - if (sz > T_INT64) - return false; - if (type == T_CPLX|T_BOOL) - return false; - /* no unsigned float or complex unsigned */ - if (type & T_UNSIGNED) { - if ((sz > T_INT && sz != T_INT64) || sz == T_BOOL || type&T_CPLX) - return false; - } - return true; -} - -/* an important function: some stream routines need to call this at - various points to ensure proper coexistence with bitwise I/O */ -static void stream_bit_flush(stream_t *s) -{ - if (s->bitpos > 0) { - stream_write(s, &s->bitbuf, 1); - s->bitpos = 0; - } -} - -void stream_flush(stream_t *s) -{ - stream_bit_flush(s); - s->funcs->flush(s); -} - -void stream_free(stream_t *s) -{ - stream_flush(s); - s->funcs->free_func(s); -} - -int stream_readfd(stream_t *s) -{ - if (is_filestream(s)) { - return fileno(s->fptr); - } - else if (is_pipestream(s)) { - return s->rd; - } - return -1; -} - -int stream_writefd(stream_t *s) -{ - if (is_filestream(s)) { - return fileno(s->fptr); - } - else if (is_pipestream(s)) { - return s->wd; - } - return -1; -} - - -/* file stream */ - -off_t fs_seek(struct _stream *s, off_t where) -{ - FILE *f = s->fptr; - - stream_bit_flush(s); - - if (fseek(f, where, SEEK_SET) == -1) - return -1; - s->pos = ftell(f); - return s->pos; -} - -off_t fs_skip(struct _stream *s, off_t offs) -{ - FILE *f = s->fptr; - - stream_bit_flush(s); - - // a successful fseek always resets the end-of-file condition, even if - // the offset is zero. we change this so that moving by 0 bytes when you're - // at eof means you stay at eof. - if (offs == 0) - return s->pos; - - if (fseek(f, offs, SEEK_CUR) == -1) - return -1; - s->pos += offs; - return s->pos; -} - -off_t fs_seek_end(struct _stream *s) -{ - FILE *f = s->fptr; - - stream_bit_flush(s); - - if (fseek(f, 0, SEEK_END) == -1) - return -1; - s->pos = ftell(f); - return s->pos; -} - -size_t fs_read(struct _stream *s, char *dest, size_t size) -{ - FILE *f = s->fptr; - size_t c; - - c = fread(dest, 1, size, f); /* read single-byte entities */ - s->pos += c; - return c; -} - -size_t fs_write(struct _stream *s, char *data, size_t size) -{ - FILE *f = s->fptr; - size_t c; - - c = fwrite(data, 1, size, f); - s->pos += c; - return c; -} - -size_t fs_trunc(struct _stream *s, size_t size) -{ - FILE *f = s->fptr; - -#ifndef WIN32 - if (ftruncate(fileno(f), s->pos) == -1) - return -1; // TODO this should be unsigned! -#else - if (_chsize(_fileno(f), s->pos) == -1) - return -1; -#endif - return s->pos; -} - -void fs_flush(struct _stream *s) -{ - FILE *f = s->fptr; - - (void)fflush(f); -} - -bool_t fs_eof(struct _stream *s) -{ - return (bool_t)feof(s->fptr); -} - -void free_fs_stream(stream_t *s) -{ - fclose(s->fptr); - free(s->name); -} - -void stream_close(stream_t *s) -{ - /* - if (!is_filestream(s)) - return; - */ - stream_flush(s); - // so far file streams are not designed to exist in the closed state - // fclose(s->fptr); -} - -stream_interface_t fs_funcs = - {free_fs_stream, fs_seek, fs_seek_end, fs_skip, - fs_read, fs_write, fs_trunc, fs_eof, fs_flush}; - -stream_t *filestream_new(stream_t *s, - char *fName, bool_t create, bool_t rewrite) -{ - FILE *f; - size_t sz; - - if (create) { - if (rewrite) { - f = fopen(fName, "w+b"); - } - else { - f = fopen(fName, "a+b"); - if (f) - fseek(f, 0, SEEK_SET); - } - } - else { - f = fopen(fName, "r+b"); - } - if (f == NULL) { - /* try readonly */ - f = fopen(fName, "rb"); - if (f == NULL) - return NULL; - } - - s->fptr = f; - s->name = strdup(fName); - - s->funcs = &fs_funcs; - - s->pos = 0; - s->bitpos = s->bitbuf = 0; - s->byteswap = false; - return s; -} - -stream_t *stream_fromfile(stream_t *s, FILE *f, char *name) -{ - s->fptr = f; - s->name = strdup(name); - - s->funcs = &fs_funcs; - - s->pos = 0; - s->bitpos = s->bitbuf = 0; - s->byteswap = false; - return s; -} - -/* memory stream */ - -off_t ms_seek(struct _stream *s, off_t where) -{ - if ((size_t)where > s->size) - return -1; - - stream_bit_flush(s); - s->pos = where; - - return s->pos; -} - -off_t ms_skip(struct _stream *s, off_t offs) -{ - if (s->pos+offs < 0 || s->pos+offs > s->size) - return -1; - - stream_bit_flush(s); - - s->pos += offs; - return s->pos; -} - -off_t ms_seek_end(struct _stream *s) -{ - stream_bit_flush(s); - s->pos = s->size; - return s->pos; -} - -size_t ms_read(struct _stream *s, char *dest, size_t size) -{ - size_t amt = size; - - assert(s->pos <= s->size); - - if (size == 0) - return 0; - - if (s->size - s->pos < size) - amt = s->size - s->pos; - - if (amt > 0) { - memcpy(dest, &s->data[s->pos], amt); - } - - s->pos += amt; - return amt; -} - -static char *ms_realloc(stream_t *s, size_t size) -{ - char *temp; - - if (size <= s->maxsize) - return s->data; - - /* UNOFFICIALLY, we put a '\0' at the end of every memory stream for - compatability with C library string functions, which are convenient. - You are not allowed to depend on this behavior; it may eventually - change. - - We implement this by telling everybody that maxsize is one less than - the actual size of the buffer. They think the last byte is at index - maxsize-1, but it is actually at index maxsize. - - data[s->size] and data[s->maxsize] are kept at '\0'. */ - - if (size <= N_STREAM_LOCAL-1) { - /* TO DO: if we want to allow shrinking, see if the buffer shrank - down to this size, in which case we need to copy. */ - s->data = &s->local[0]; - s->maxsize = N_STREAM_LOCAL-1; - s->data[s->maxsize] = '\0'; - return s->data; - } - if (s->data == &s->local[0]) { - temp = malloc(size+1); - // TODO nullcheck - memcpy(temp, s->data, s->size); - } - else { - /* here we rely on the realloc() behavior of - doing a malloc() when passed a NULL pointer. */ - temp = realloc(s->data, size+1); - if (temp == NULL) - return NULL; - } - s->data = temp; - s->maxsize = size; - s->data[s->maxsize] = '\0'; - return s->data; -} - -size_t ms_trunc(struct _stream *s, size_t size) -{ - if (size == s->size) - return size; - - if (size < s->size) { - // TODO: if big shrink, release space - if (s->pos > size) - s->pos = size; - } - else { - if (ms_realloc(s, size) == NULL) - return s->size; - } - - s->size = size; - s->data[size] = '\0'; - return size; -} - -size_t ms_write(struct _stream *s, char *data, size_t size) -{ - size_t amt; - size_t newsize; - - if (size == 0) - return 0; - - if (s->pos + size > s->size) { - if (s->pos + size > s->maxsize) { - /* TO DO: here you might want to add a mechanism for limiting - the growth of the stream. */ - newsize = s->maxsize * 2; - while (s->pos + size > newsize) - newsize *= 2; - if (ms_realloc(s, newsize) == NULL) { - /* no more space; write as much as we can */ - amt = s->maxsize - s->pos; - if (amt > 0) { - memcpy(&s->data[s->pos], data, amt); - } - s->pos += amt; - s->size = s->maxsize; - /* in this case we've written up to the end of the buffer, - so we know the next char is \0 since ms_realloc sets that - up every time it allocates. */ - return amt; - } - } - s->size = s->pos + size; - - /* always valid since secretly we know the buffer is 1 bigger than - maxsize */ - s->data[s->size] = '\0'; - } - memcpy(&s->data[s->pos], data, size); - s->pos += size; - - return size; -} - -void ms_flush(struct _stream *s) -{ -} - -bool_t ms_eof(struct _stream *s) -{ - assert(s->pos <= s->size); - return (bool_t)(s->pos == s->size); -} - -void free_ms_stream(stream_t *s) -{ - if (s->data != NULL && s->data != &s->local[0]) - free(s->data); -} -/* -stream_t *memstream_copy(stream_t *s) -{ - stream_t *ns = memstream_new(s->size); - - ms_write(ns, s->s, s->size); - stream_seek(ns, 0); - return ns; -} -*/ -stream_interface_t ms_funcs = - {free_ms_stream, ms_seek, ms_seek_end, ms_skip, - ms_read, ms_write, ms_trunc, ms_eof, ms_flush}; - -stream_t *memstream_new(stream_t *s, size_t initsize) -{ - s->pos = 0; - s->size = 0; - s->data = &s->local[0]; - s->maxsize = N_STREAM_LOCAL-1; - s->data[s->maxsize] = '\0'; - - if (ms_realloc(s, initsize) == NULL) - julia_outofmemory(); - - s->data[initsize] = '\0'; - s->data[s->pos] = '\0'; - s->size = initsize; - - s->funcs = &ms_funcs; - - s->bitpos = s->bitbuf = 0; - s->byteswap = false; - - return s; -} - -#if 0 -string_t *string_new(int len) -{ - string_t *str; - - str = memstream_new(len); - str->len = len; - - return str; -} - -/* this function makes string streams from C strings (NUL-term) */ -string_t *string_fromc(char *s) -{ - string_t *str; - int len = strlen(s); - - str = string_new(len); - stream_write(str, s, len); - stream_seek(str, 0); - - return str; -} -#endif - -/* pipe */ -off_t ps_seek(struct _stream *s, off_t where) -{ - return -1; -} - -size_t ps_read(struct _stream *s, char *dest, size_t size); - -off_t ps_skip(struct _stream *s, off_t offs) -{ - char buf[CHUNK_SIZE]; - int rd = s->rd; - size_t c, amt; - - if (offs < 0) - return -1; - while (offs > 0) { - amt = offs > CHUNK_SIZE ? CHUNK_SIZE : offs; - c = ps_read(s, buf, amt); - if (c < amt) - return 0; - offs -= c; - } - return 0; -} - -off_t ps_seek_end(struct _stream *s) -{ - return -1; -} - -size_t ps_read(struct _stream *s, char *dest, size_t size) -{ - if (ps_eof(s)) - return 0; -#ifdef WIN32 - int c = _read(s->rd, dest, size); -#else - ssize_t c = read(s->rd, dest, size); -#endif - if (c < 0) - return 0; - return (size_t)c; -} - -size_t ps_write(struct _stream *s, char *data, size_t size) -{ -#ifdef WIN32 - int c = _write(s->wd, data, size); -#else - ssize_t c = write(s->wd, data, size); -#endif - if (c < 0) - return 0; - return c; -} - -size_t ps_trunc(struct _stream *s, size_t size) -{ - return 0; -} - -void ps_flush(struct _stream *s) -{ -} - -bool_t ps_eof(struct _stream *s) -{ -#ifndef WIN32 - fd_set set; - struct timeval tv = {0, 0}; - - FD_ZERO(&set); - FD_SET(s->rd, &set); - return (select(s->rd+1, &set, NULL, NULL, &tv)==0); -#else - return 0; -#endif -} - -void free_ps_stream(stream_t *s) -{ - close(s->rd); - close(s->wd); -} - -stream_interface_t ps_funcs = - {free_ps_stream, ps_seek, ps_seek_end, ps_skip, - ps_read, ps_write, ps_trunc, ps_eof, ps_flush}; - -stream_t *pipestream_new(stream_t *s, int flags) -{ - int fds[2]; - - s->funcs = &ps_funcs; - -#ifdef WIN32 - _pipe(&fds[0], 32768, _O_BINARY | flags); -#else - pipe(&fds[0]); -#endif - s->rd = fds[0]; s->wd = fds[1]; - - s->byteswap = false; - s->bitpos = s->bitbuf = 0; - s->pos = 0; - - return s; -} - - -/* high-level stream functions */ - -/* type is a "T_" code as defined in streams.h */ -int stream_put_num(stream_t *stream, char *d, u_int32_t type) -{ - int c, sz, i; - - assert(valid_type(type)); - sz = type_sizes[type]; - - if (!stream->byteswap) { - c = stream_write(stream, d, sz); - } - else if (sz >= 4) { - char temp[32]; - if (type & T_CPLX) { - bswap_to(temp, (byte_t*)d, sz/2); - bswap_to(temp+sz/2, (byte_t*)d+sz/2, sz/2); - } - else { - bswap_to(temp, (byte_t*)d, sz); - } - c = stream_write(stream, temp, sz); - } - else { - assert(sz == 2 || sz == 1); - if (type & T_CPLX) { - c = stream_write(stream, &d[0], 2); - /* - for(i=sz/2-1; i >= 0; i--) { - c += stream_write(stream, &d[i], 1); - } - for(i=sz-1; i >= sz/2; i--) { - c += stream_write(stream, &d[i], 1); - } - */ - } - else { - c = 0; - if (sz == 2) - c += stream_write(stream, &d[1], 1); - c += stream_write(stream, &d[0], 1); - } - } - - return c; -} - -int stream_get_num(stream_t *s, char *data, u_int32_t type) -{ - int c, sz; - - assert(valid_type(type)); - sz = type_sizes[type]; - - c = stream_read(s, data, sz); - - if (s->byteswap && c == sz) { - if (type & T_CPLX) { - bswap((byte_t*)data, sz/2); - bswap((byte_t*)data+sz/2, sz/2); - } - else { - bswap((byte_t*)data, sz); - } - } - if (c < sz) - return -1; - return c; -} - -int stream_put_int(stream_t *s, int n) -{ - return stream_put_num(s, (char*)&n, T_INT); -} - -int stream_put_char(stream_t *s, u_int32_t wc) -{ - char buf[8]; - int amt; - - amt = u8_wc_toutf8(buf, wc); - return stream_write(s, buf, amt); -} - -int stream_put_stringz(stream_t *s, char *str, bool_t nulterm) -{ - int c, l = strlen(str); - - c = stream_write(s, str, l); - if (nulterm) - c += stream_write(s, &str[l], 1); - return c; -} - -int stream_get_char(stream_t *s, u_int32_t *pwc) -{ - char buf[8]; - int amt; - unsigned int i; - - amt = stream_read(s, buf, 1); - if (amt == 0) - return 0; - amt = u8_seqlen(buf) - 1; // find out how many more bytes in this seq - if (amt) { - stream_read(s, &buf[1], amt); - } - amt++; - buf[amt] = '\0'; - i=0; - *pwc = u8_nextmemchar(buf, &i); - return i; -} - -int stream_nextchar(stream_t *s) -{ - u_int32_t wc; - - if (is_memstream(s)) { - if (stream_eof(s)) - return -1; - stream_bit_flush(s); - s->pos++; - while (!stream_eof(s) && !isutf(s->s[s->pos])) - s->pos++; - return s->pos; - } - - if (stream_get_char(s, &wc) == 0) - return -1; - return s->pos; -} - -int stream_prevchar(stream_t *s) -{ - char c; - - if (is_memstream(s)) { - if (s->pos == 0) - return -1; - stream_bit_flush(s); - s->pos--; - while (s->pos > 0 && !isutf(s->s[s->pos])) - s->pos--; - return s->pos; - } - - do { - if (stream_skip(s, -1) == -1) - return -1; - stream_read(s, &c, 1); - stream_skip(s, -1); - } while(!isutf(c)); - return s->pos; -} - -void stream_put_bit(stream_t *s, int bit) -{ - byte_t mask = 0x1; - - if (s->bitpos == 0) { - if (!stream_read(s, &s->bitbuf, 1)) { - s->bitbuf = 0; - } - else { - stream_skip(s, -1); - } - } - - mask <<= s->bitpos; - if (bit) - s->bitbuf |= mask; - else - s->bitbuf &= ~mask; - s->dirty = 1; - - s->bitpos++; - if (s->bitpos > 7) { - s->bitpos = 0; - stream_write(s, &s->bitbuf, 1); - } -} - -int stream_get_bit(stream_t *s, int *pbit) -{ - byte_t mask = 0x1; - - if (s->bitpos == 0) { - if (!stream_read(s, &s->bitbuf, 1)) { - return 0; - } - else { - stream_skip(s, -1); - } - s->dirty = 0; - } - - mask <<= s->bitpos; - *pbit = (s->bitbuf & mask) ? 1 : 0; - - s->bitpos++; - - if (s->bitpos > 7) { - s->bitpos = 0; - if (s->dirty) { - stream_write(s, &s->bitbuf, 1); - } - else { - stream_skip(s, 1); - } - } - return 1; -} - -/* warning: DO NOT write a trivial wrapper for this function; it allows - easily crashing the interpreter using unfriendly format strings. - - also, this function is designed to print small things like messages. it - cannot print arbitrarily large data. to do that, use stream_write, - or repeated calls to this function. - - TODO: this doesn't handle UTF-8 properly: - -printf("%*s|\n%*s|\n", -4, "X", -4, "a") -printf("%-4s|\n%-4s|\n", "X", "a") -X | -a | - -Where X is a 2-byte character. -*/ -int stream_printf(stream_t *s, char *format, ...) -{ - int c; - va_list args; - char buf[512]; - - va_start(args, format); - c = vsnprintf(buf, sizeof(buf), format, args); - va_end(args); - - if (c < 0) - return 0; - - if ((unsigned)c > sizeof(buf)) - c = sizeof(buf); - - return stream_write(s, buf, c); -} - -char *stream_take_buffer(stream_t *s, size_t *size) -{ - char *buf; - - if (!is_memstream(s) || s->data == NULL) - return NULL; - - stream_flush(s); - - if (s->data == &s->local[0]) { - buf = malloc(s->size+1); - if (buf == NULL) - return NULL; - memcpy(buf, s->data, s->size+1); - buf[s->size] = '\0'; - } - else { - buf = s->data; - } - - *size = s->size+1; /* buffer is actually 1 bigger for terminating NUL */ - - /* empty stream and reinitialize */ - s->data = &s->local[0]; - s->maxsize = N_STREAM_LOCAL-1; - s->data[s->maxsize] = '\0'; - stream_trunc(s, 0); - - return buf; -} - -/* Chunk size for reading lines: if too small, then we make too many low-level - calls. if too large, then we waste time reading bytes beyond the end of the - current line. this is effectively a guess as to how big a line is. - this value should be < N_STREAM_LOCAL, allowing at least some lines to - fit without extra allocation. */ -#define LINE_CHUNK_SIZE (N_STREAM_LOCAL-1) - -int stream_readline(stream_t *dest, stream_t *s, char delim) -{ - char chunk[LINE_CHUNK_SIZE]; - int i, cnt, total=0; - - if (stream_eof(s)) - return 0; - - do { - cnt = stream_read(s, chunk, LINE_CHUNK_SIZE); - for(i=0; i < cnt; i++) { - if (chunk[i] == delim) - break; - } - if (i < cnt) { - total += stream_write(dest, chunk, i+1); - stream_skip(s, -(cnt-(i+1))); - break; - } - total += stream_write(dest, chunk, cnt); - } while (!stream_eof(s)); - - return total; -} - -/* extract one line of text from a stream, into a memory buffer. - a pointer to the buffer is returned in *pbuf, the size of the buffer - in *psz, and the number of characters in the line (including newline) is - returned. the line may contain NULs, but there will also be a NUL - terminator as the last character in the buffer. - - This routine's behavior is not exactly the same as GNU getline. In - particular, it always allocates a buffer. -*/ -int stream_getline(stream_t *s, char **pbuf, size_t *psz) -{ - stream_t buf; - - memstream_new(&buf, 0); - - stream_readline(&buf, s, '\n'); - - *pbuf = stream_take_buffer(&buf, psz); - - return *psz-1; -} - -int stream_get_stringz(stream_t *dest, stream_t *src) -{ - return stream_readline(dest, src, '\0'); -} - -/* get n UTF-8 characters */ -int stream_get_stringn(stream_t *dest, stream_t *src, size_t c) -{ - u_int32_t wc; - size_t cnt=0; - - while (c > 0) { - if (stream_get_char(src, &wc) == 0 || - stream_put_char(dest, wc) == 0) - break; - c--; - cnt++; - } - return cnt; -} - -/* TODO: change API to allow passing a heap-allocated page-aligned - chunk to reuse on each copy. if it's NULL we alloc our own. */ -int stream_copy(stream_t *to, stream_t *from, size_t nbytes, bool_t all) -{ - int c=0, cnt, wc, rdc; - char buf[CHUNK_SIZE]; - int remain = all ? CHUNK_SIZE : nbytes; - - if (is_memstream(to)) { - // avoid extra copy, read directly into memstream - while (!stream_eof(from)) { - if (all) { - rdc = CHUNK_SIZE; - } - else { - /* if !all, only 1 call to stream_read needed */ - rdc = nbytes; - } - - if (ms_realloc(to, to->pos + rdc) == NULL) { - rdc = to->maxsize - to->pos; - if (rdc == 0) - break; - } - cnt = stream_read(from, &to->s[to->pos], rdc); - wc = cnt; - to->pos += wc; - if (to->pos > to->size) { - to->size = to->pos; - to->s[to->size] = '\0'; - } - c += wc; - - if (!all) - remain -= wc; - if (wc < rdc || remain == 0) - break; - } - } - else if (is_memstream(from)) { - while (1) { - if (all) { - rdc = CHUNK_SIZE; - } - else { - /* if !all, only 1 call to stream_read needed */ - rdc = nbytes; - } - // check for source out of data - if (from->size - from->pos < rdc) { - remain = rdc = from->size - from->pos; - } - cnt = stream_write(to, &from->s[from->pos], rdc); - wc = cnt; - from->pos += wc; - c += wc; - if (!all) - remain -= wc; - if (wc < rdc || remain == 0) - break; - } - } - else { - while (!stream_eof(from)) { - rdc = remain>CHUNK_SIZE ? CHUNK_SIZE : remain; - - cnt = stream_read(from, buf, rdc); - wc = stream_write(to, buf, cnt); - c += wc; - - if (!all) - remain -= wc; - if (wc < rdc || remain == 0) - break; - } - } - return c; -} - - -/* serialization functions */ - -/* nbytes is either 4 or 8 */ -size_t stream_get_offset(stream_t *s, off_t *po, int nbytes) -{ - size_t c; - int64_t off64; - int32_t off32; - - if (nbytes == 4) { - c = stream_read(s, (char*)&off32, nbytes); - if (c < nbytes) - return c; - if (s->byteswap) - off32 = bswap_32(off32); - /* OK on either system since off_t is >= off32 in size */ - *po = (off_t)off32; - } - else { - c = stream_read(s, (char*)&off64, nbytes); - if (c < nbytes) - return c; - if (s->byteswap) - off64 = bswap_64(off64); - if (sizeof(off_t) == 8) { - *po = (off_t)off64; - } - else { - if (off64 <= INT_MAX && off64 >= INT_MIN) { - // downcast safe - *po = (off_t)off64; - } - else { - cerror("I/O error: 64-bit offset truncated on input.\n"); - } - } - } - - return c; -} - -size_t stream_put_offset(stream_t *s, off_t o, int nbytes) -{ - int64_t off64; - int32_t off32; - - if (nbytes == 4) { - if (sizeof(off_t) == 8 && (o > INT_MAX || o < INT_MIN)) { - cerror("I/O error: 64-bit offset truncated on output.\n"); - } - off32 = (int32_t)o; - if (s->byteswap) - off32 = bswap_32(off32); - return stream_write(s, (char*)&off32, 4); - } - off64 = (int64_t)o; - if (s->byteswap) - off64 = bswap_64(off64); - return stream_write(s, (char*)&off64, 8); -} diff --git a/llt/attic/streams.h b/llt/attic/streams.h deleted file mode 100644 index 1f25f3b..0000000 --- a/llt/attic/streams.h +++ /dev/null @@ -1,213 +0,0 @@ -#ifndef __STREAMS_H_ -#define __STREAMS_H_ - -struct _stream; - -// numeric type codes -#define T_BOOL 0x000 -#define T_BYTE 0x001 -#define T_SHORT 0x002 -#define T_INT 0x003 -#define T_FLOAT 0x004 -#define T_DOUBLE 0x005 -#define T_INT64 0x006 -//#define T_LDOUBLE 0x007 -#define T_UNSIGNED 0x008 -#define T_CPLX 0x010 - -#define T_TYPEMASK 0x1f /* bits related to numeric type */ -#define T_TYPESIZE 0x07 /* bits related to type size */ - -#define is_type(a, t) (((a) & T_TYPESIZE) == (t)) -// type_bitseq tells whether 2 types are bit-representation compatible -#define type_bitseq(a, b) (((a) & ~T_UNSIGNED) == ((b) & ~T_UNSIGNED)) - -extern unsigned int type_sizes[]; - -typedef struct { - void (*free_func)(struct _stream *s); - /* these return -1 on error, or new position if successful */ - /* set absolute position */ - off_t (*seek)(struct _stream *s, off_t where); - /* seek to end (past last byte) */ - off_t (*seek_end)(struct _stream *s); - /* move relative to current position */ - off_t (*skip)(struct _stream *s, off_t offs); - - /* these return # of bytes read/written, 0 on error */ - size_t (*read)(struct _stream *s, char *dest, size_t size); - size_t (*write)(struct _stream *s, char *data, size_t size); - - /* truncate a stream to the given length */ - size_t (*trunc)(struct _stream *s, size_t size); - - /* no data left? */ - bool_t (*eof)(struct _stream *s); - - /* sync bit buffer, and sync to hardware if applicable */ - void (*flush)(struct _stream *s); - /* could add fsync() call for durable writes */ -} stream_interface_t; - -extern stream_interface_t fs_funcs; -extern stream_interface_t ms_funcs; -extern stream_interface_t ps_funcs; - -#define is_memstream(s) (((stream_t*)s)->funcs==&ms_funcs) -#define is_filestream(s) (((stream_t*)s)->funcs==&fs_funcs) -#define is_pipestream(s) (((stream_t*)s)->funcs==&ps_funcs) - -/* general i/o chunk size */ -#define CHUNK_SIZE 4096 - -/* this should be a multiple of 4; otherwise the struct gets padded to - the next multiple of 4 anyway, wasting space */ -#define N_STREAM_LOCAL 40 - -typedef struct _stream { - /* unfortunately, it seems that pos needs to be a signed type to be - compatible with OS functions. */ - off_t pos; - byte_t bitpos; /* offset within a byte, for writing individual bits */ - byte_t bitbuf; /* a copy of the byte at the current stream position */ - char ungotc; - struct { - /* does bit buffer need to be written? */ - unsigned char dirty:1; - unsigned char byteswap:1; - unsigned char readonly:1; - unsigned char ungot:1; - }; - - stream_interface_t *funcs; - - /* stream-specific data */ - union { - char *name; - size_t maxsize; - int rd; // pipe read descriptor - }; - union { - FILE *fptr; - char *data; - char *s; - int wd; // pipe write descriptor - }; - union { - /* this is always a size in BYTES */ - size_t size; - size_t len; - }; - char local[N_STREAM_LOCAL]; -} stream_t; - -#include - -stream_t *filestream_new(stream_t *s, char *fName, - bool_t create, bool_t rewrite); -stream_t *memstream_new(stream_t *s, size_t initsize); -stream_t *pipestream_new(stream_t *s, int flags); -stream_t *stream_fromfile(stream_t *s, FILE *f, char *name); -//string_t *string_new(int len); -//string_t *string_fromc(char *s); -stream_t *memstream_copy(stream_t *s); -void stream_free(stream_t *s); -void stream_flush(stream_t *s); - - -/* high level stream functions */ - -/* 'all' means copy to end of stream */ -int stream_copy(stream_t *to, stream_t *from, size_t nbytes, bool_t all); - -int stream_put_num(stream_t *s, char *data, u_int32_t type); -int stream_put_int(stream_t *s, int n); -int stream_put_char(stream_t *s, u_int32_t wc); -int stream_put_stringz(stream_t *s, char *str, bool_t nulterm); - -/* single-bit I/O - even works for mixed reads and writes. - mixing bit-level I/O with normal byte stream I/O has undefined effects and - will almost certainly destroy your file. however, it is safe to switch - between bit and byte I/O if you call stream_flush in between. */ -void stream_put_bit(stream_t *s, int bit); - -/* warning: this uses a fixed-size buffer. it is intended only for printing - normal things like "a= %d". if you might be printing a large buffer, you - should use stream i/o functions directly. */ -int stream_printf(stream_t *s, char *format, ...); - - -/* high level stream functions - input */ - -int stream_get_num(stream_t *s, char *data, u_int32_t type); -int stream_get_char(stream_t *s, u_int32_t *pwc); -int stream_get_stringz(stream_t *dest, stream_t *src); -int stream_get_stringn(stream_t *dest, stream_t *src, size_t c); -int stream_readline(stream_t *dest, stream_t *s, char delim); -int stream_getline(stream_t *s, char **pbuf, size_t *psz); -/* returns # of bits read (0 or 1) */ -int stream_get_bit(stream_t *s, int *pbit); - -int stream_nextchar(stream_t *s); -int stream_prevchar(stream_t *s); - -void stream_close(stream_t *s); - -/* TODO */ -// stream_fgetc -// stream_ungetc - -/* get underlying file descriptors, -1 if none */ -int stream_readfd(stream_t *s); -int stream_writefd(stream_t *s); - -/* - low level stream functions - - Streams are intended to provide a uniform function interface to various - kinds of byte streams. - - The eight low-level stream functions (below) are intended to be light weight. - It must be easy to implement reasonably efficient higher-level stream - functions, therefore any complexity required to make (for example) single - byte reads and writes efficient must be implemented by the stream. - - Note that you can implement file streams using fread(), fwrite(), etc. - because buffering is already implemented in every standard C library. These - calls do not make system calls in general, and are perfectly fine to use. -*/ - -#define stream_seek(s, w) (s)->funcs->seek(s, w) -#define stream_seek_end(s) (s)->funcs->seek_end(s) -#define stream_skip(s, o) (s)->funcs->skip(s, o) -#define stream_read(s, d, sz) (s)->funcs->read(s, (char*)d, sz) -#define stream_write(s, d, sz) (s)->funcs->write(s, (char*)d, sz) -#define stream_trunc(s, sz) (s)->funcs->trunc(s, sz) -#define stream_eof(s) (s)->funcs->eof(s) - - -STATIC_INLINE size_t stream_put_byte(stream_t *s, byte_t b) -{ - return stream_write(s, (char*)&b, 1); -} - -STATIC_INLINE size_t stream_get_byte(stream_t *s, byte_t *pb) -{ - return stream_read(s, (char*)pb, 1); -} - -#define stream_puts(s, str) stream_write(s, str, strlen(str)) - -/* - stream_take_buffer - - This lets you get the data of a stream without having to copy it. In order - not to either lose the buffer or free it twice, this operation effectively - empties the stream. In other words, size goes to 0, data becomes NULL. - Whoever called the function takes full responsibility for the buffer. - You must free it eventually. - "size" gets set to the size of the data in the buffer. -*/ -char *stream_take_buffer(stream_t *s, size_t *size); - -#endif diff --git a/llt/attic/trash.c b/llt/attic/trash.c deleted file mode 100644 index 0046840..0000000 --- a/llt/attic/trash.c +++ /dev/null @@ -1,68 +0,0 @@ -/* moving data in small power-of-2 sized units */ -void copy_el(char *dest, char *src, size_t sz) -{ - switch (sz) { - case 16: - *(int64_t*)&dest[0] = *(int64_t*)&src[0]; - *(int64_t*)&dest[8] = *(int64_t*)&src[8]; - break; - case 8: *(int64_t*)dest = *(int64_t*)src; break; - case 4: *(int32_t*)dest = *(int32_t*)src; break; - case 2: *(int16_t*)dest = *(int16_t*)src; break; - case 1: *dest = *src; break; - } -} - -void swap_el(char *a, char *b, size_t sz) -{ - int64_t i64; - int32_t i32; - int16_t i16; - int8_t i8; - switch (sz) { - case 16: - i64 = *(int64_t*)&a[0]; - *(int64_t*)&a[0] = *(int64_t*)&b[0]; - *(int64_t*)&b[0] = i64; - i64 = *(int64_t*)&a[8]; - *(int64_t*)&a[8] = *(int64_t*)&b[8]; - *(int64_t*)&b[8] = i64; - break; - case 8: - i64 = *(int64_t*)a; - *(int64_t*)a = *(int64_t*)b; - *(int64_t*)b = i64; - break; - case 4: - i32 = *(int32_t*)a; - *(int32_t*)a = *(int32_t*)b; - *(int32_t*)b = i32; - break; - case 2: - i16 = *(int16_t*)a; - *(int16_t*)a = *(int16_t*)b; - *(int16_t*)b = i16; - break; - case 1: - i8 = *a; - *a = *b; - *b = i8; - break; - } -} - -void neg_any(void *dest, void *a, numerictype_t tag) -{ - switch (tag) { - case T_INT8: *(int8_t *)dest = -*(int8_t *)a; break; - case T_UINT8: *(uint8_t *)dest = -*(uint8_t *)a; break; - case T_INT16: *(int16_t *)dest = -*(int16_t *)a; break; - case T_UINT16: *(uint16_t*)dest = -*(uint16_t*)a; break; - case T_INT32: *(int32_t *)dest = -*(int32_t *)a; break; - case T_UINT32: *(uint32_t*)dest = -*(uint32_t*)a; break; - case T_INT64: *(int64_t *)dest = -*(int64_t *)a; break; - case T_UINT64: *(uint64_t*)dest = -*(uint64_t*)a; break; - case T_FLOAT: *(float *)dest = -*(float *)a; break; - case T_DOUBLE: *(double *)dest = -*(double *)a; break; - } -} diff --git a/llt/scrap b/llt/scrap deleted file mode 100644 index ad1f63f..0000000 --- a/llt/scrap +++ /dev/null @@ -1,176 +0,0 @@ -/* null stream */ -off_t null_seek(struct _stream *s, off_t where) -{ - return -1; -} - -off_t null_skip(struct _stream *s, off_t offs) -{ - return 0; -} - -off_t null_seek_end(struct _stream *s) -{ - return -1; -} - -size_t null_read(struct _stream *s, char *dest, size_t size) -{ - return 0; -} - -size_t null_write(struct _stream *s, char *data, size_t size) -{ - return 0; -} - -size_t null_trunc(struct _stream *s, size_t size) -{ - return 0; -} - -void null_flush(struct _stream *s) -{ -} - -bool_t null_eof(struct _stream *s) -{ - return true; -} - -void free_null_stream(stream_t *s) -{ -} - -DLLEXPORT stream_interface_t null_funcs = - {free_null_stream, null_seek, null_seek_end, null_skip, - null_read, null_write, null_trunc, null_eof, null_flush}; - -stream_t *nullstream_new() -{ - stream_t *s; - - s = (stream_t*)obj_alloc(stream_pool); - s->funcs = &null_funcs; - s->byteswap = false; - s->bitpos = s->bitbuf = 0; - s->pos = 0; - - return s; -} - -void free_roms_stream(stream_t *s) -{ - (void)s; -} - -size_t roms_write(struct _stream *s, char *data, size_t size) -{ - (void)s; - (void)data; - (void)size; - return 0; -} - -size_t roms_trunc(struct _stream *s, size_t size) -{ - (void)size; - return s->size; -} - -void roms_flush(struct _stream *s) -{ - s->bitpos = 0; -} - -stream_interface_t roms_funcs = - {free_roms_stream, ms_seek, ms_seek_end, ms_skip, - ms_read, roms_write, roms_trunc, ms_eof, roms_flush}; - -/* read-only memory stream */ -stream_t *romemstream_new(stream_t *s, char *data, size_t len) -{ - memstream_new(s, 0); - - s->funcs = &roms_funcs; - - s->data = data; - s->size = len; - s->maxsize = len+1; - s->pos = 0; - s->bitpos = s->bitbuf = 0; - s->byteswap = false; - - return s; -} - -int stream_vput_int(stream_t *s, int nargs, ...) -{ - u_int32_t val, i, c=0; - va_list ap; - - va_start(ap, nargs); - for(i=0; i < (unsigned)nargs; i++) { - val = va_arg(ap, int); - c += stream_put_int(s, val); - } - va_end(ap); - - return c; -} - -// after this function you are guaranteed to be able to perform -// operations of the kind requested. -static int _ios_setstate(ios_t *s, iostate_t newstate) -{ - if (s->state != newstate) { - if (s->state == iost_none || s->bm == bm_mem || s->bm == bm_none) { - } - else if (s->state == iost_rd) { - // reading -> writing; try to put back unused buffer data - // todo: another possibility here is to seek back s->size bytes, - // not move any data, and retain the ability to seek backwards - // within the buffer. the downside to that would be redundant - // writes of stuff that was already in the file. - ios_skip(s, -(off_t)(s->size - s->bpos)); - // todo: if the seek fails...? - _discard_partial_buffer(s); - // note: bitpos is left alone, so if all goes well we pick up - // writing exactly where we stopped reading. - } - else if (s->state == iost_wr) { - ios_flush(s); - } - s->state = newstate; - } - - // now make sure buffer is set up for the state we're in - if (s->state == iost_wr) { - // TODO: fill buffer if stenciling is requested - } - else if (s->state == iost_rd) { - // TODO: fill buffer if needed - } - - return 0; -} - - -/* convert double to int64 in software */ -int64_t double_to_int64(double d) -{ - int64_t i; - int ex; - union ieee754_double dl; - - if (fabs(d) < 1) return 0; - - dl.d = d; - ex = dl.ieee.exponent - IEEE754_DOUBLE_BIAS; - // fill mantissa into bits 0 to 51 - i = ((((int64_t)dl.mantissa0)<<32) | ((int64_t)dl.mantissa1)); - if (ex < 52) - i >>= (52-ex); - else if (ex > 52) - i <<= (ex-52); -}