remove more unused stuff

This commit is contained in:
Jeff Bezanson 2013-06-11 18:15:48 -04:00
parent 92542d0b78
commit 518415febf
10 changed files with 2 additions and 2248 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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
View File

@ -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);
}