+ U8 b1=0,b2=0;
+ if(r->read(r, &b1, 1)<1) {
+ fprintf(stderr, "bitio.c:reader_readU16: Read over end of memory region\n");
+ }
+ if(r->read(r, &b2, 1)<1) {
+ fprintf(stderr, "bitio.c:reader_readU16: Read over end of memory region\n");
+ }
+ return b1|b2<<8;
+}
+U32 reader_readU32(reader_t*r)
+{
+ U8 b1=0,b2=0,b3=0,b4=0;
+ if(r->read(r, &b1, 1)<1)
+ fprintf(stderr, "bitio.c:reader_readU32: Read over end of memory region\n");
+ if(r->read(r, &b2, 1)<1)
+ fprintf(stderr, "bitio.c:reader_readU32: Read over end of memory region\n");
+ if(r->read(r, &b3, 1)<1)
+ fprintf(stderr, "bitio.c:reader_readU32: Read over end of memory region\n");
+ if(r->read(r, &b4, 1)<1)
+ fprintf(stderr, "bitio.c:reader_readU32: Read over end of memory region\n");
+ return b1|b2<<8|b3<<16|b4<<24;
+}
+float reader_readFloat(reader_t*r)
+{
+ U8 b1=0,b2=0,b3=0,b4=0;
+ r->read(r, &b1, 1);
+ r->read(r, &b2, 1);
+ r->read(r, &b3, 1);
+ r->read(r, &b4, 1);
+ U32 w = (b1|b2<<8|b3<<16|b4<<24);
+ return *(float*)&w;
+}
+double reader_readDouble(reader_t*r)
+{
+ double f;
+ r->read(r, &f, 8);
+ return f;
+
+ U8 b[8];
+ r->read(r, b, 8);
+ U64 w = ((U64)b[0]|(U64)b[1]<<8|(U64)b[2]<<16|(U64)b[3]<<24|(U64)b[4]<<32|(U64)b[5]<<40|(U64)b[6]<<48|(U64)b[7]<<56);
+ return *(double*)&w;
+}
+char*reader_readString(reader_t*r)
+{
+ writer_t g;
+ writer_init_growingmemwriter(&g, 16);
+ while(1) {
+ U8 b = reader_readU8(r);
+ writer_writeU8(&g, b);
+ if(!b)
+ break;
+ }
+ char*string = (char*)writer_growmemwrite_getmem(&g);
+ g.finish(&g);
+ return string;
+}
+
+void writer_writeString(writer_t*w, const char*s)
+{
+ int l = strlen(s);
+ char zero = 0;
+ w->write(w, (void*)s, l);
+ w->write(w, &zero, 1);
+}
+void writer_writeU8(writer_t*w, unsigned char b)
+{
+ w->write(w, &b, 1);
+}
+void writer_writeU16(writer_t*w, unsigned short v)
+{
+ unsigned char b1 = v;
+ unsigned char b2 = v>>8;
+ w->write(w, &b1, 1);
+ w->write(w, &b2, 1);
+}
+void writer_writeU32(writer_t*w, unsigned long v)
+{
+ unsigned char b1 = v;
+ unsigned char b2 = v>>8;
+ unsigned char b3 = v>>16;
+ unsigned char b4 = v>>24;
+ w->write(w, &b1, 1);
+ w->write(w, &b2, 1);
+ w->write(w, &b3, 1);
+ w->write(w, &b4, 1);
+}
+void writer_writeFloat(writer_t*w, float f)
+{
+ unsigned long v = *(unsigned long*)&f;
+ unsigned char b1 = v;
+ unsigned char b2 = v>>8;
+ unsigned char b3 = v>>16;
+ unsigned char b4 = v>>24;
+ w->write(w, &b1, 1);
+ w->write(w, &b2, 1);
+ w->write(w, &b3, 1);
+ w->write(w, &b4, 1);
+}
+void writer_writeDouble(writer_t*w, double f)
+{
+ w->write(w, &f, 8);
+ return;
+
+ unsigned long long v = *(unsigned long long*)&f;
+ unsigned char b1 = v;
+ unsigned char b2 = v>>8;
+ unsigned char b3 = v>>16;
+ unsigned char b4 = v>>24;
+ unsigned char b5 = v>>32;
+ unsigned char b6 = v>>40;
+ unsigned char b7 = v>>48;
+ unsigned char b8 = v>>56;
+ w->write(w, &b1, 1);
+ w->write(w, &b2, 1);
+ w->write(w, &b3, 1);
+ w->write(w, &b4, 1);
+ w->write(w, &b5, 1);
+ w->write(w, &b6, 1);
+ w->write(w, &b7, 1);
+ w->write(w, &b8, 1);