remove more unused stuff
This commit is contained in:
		
							parent
							
								
									a5ae9c356a
								
							
						
					
					
						commit
						c81f21fdc0
					
				|  | @ -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 | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -1,69 +0,0 @@ | |||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <assert.h> | ||||
| #include <limits.h> | ||||
| 
 | ||||
| #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; | ||||
| } | ||||
|  | @ -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 | ||||
|  | @ -1,396 +0,0 @@ | |||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <assert.h> | ||||
| #include <limits.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #ifdef WIN32 | ||||
| #include <malloc.h> | ||||
| #include <io.h> | ||||
| #include <fcntl.h> | ||||
| #define fileno _fileno | ||||
| #else | ||||
| #include <unistd.h> | ||||
| #include <sys/time.h> | ||||
| #include <sys/select.h> | ||||
| #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<<s->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<<s->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; | ||||
| } | ||||
|  | @ -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 | ||||
							
								
								
									
										1107
									
								
								llt/attic/streams.c
								
								
								
								
							
							
						
						
									
										1107
									
								
								llt/attic/streams.c
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -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 <stdio.h> | ||||
| 
 | ||||
| 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 | ||||
|  | @ -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; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										176
									
								
								llt/scrap
								
								
								
								
							
							
						
						
									
										176
									
								
								llt/scrap
								
								
								
								
							|  | @ -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); | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	 Jeff Bezanson
						Jeff Bezanson