177 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| /* 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);
 | |
| }
 |