/* 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); }