+
+/* ---------------------------- mem reader ------------------------------- */
+
+typedef struct _memread
+{
+ unsigned char*data;
+ int length;
+} memread_t;
+
+static int reader_memread(reader_t*reader, void* data, int len)
+{
+ memread_t*mr = (memread_t*)reader->internal;
+
+ if(mr->length - reader->pos < len) {
+ len = mr->length - reader->pos;
+ }
+ memcpy(data, &mr->data[reader->pos], len);
+ reader->pos += len;
+ return len;
+}
+static void reader_memread_dealloc(reader_t*reader)
+{
+ if(reader->internal)
+ free(reader->internal);
+ memset(reader, 0, sizeof(reader_t));
+}
+void reader_init_memreader(reader_t*r, void*newdata, int newlength)
+{
+ memread_t*mr = (memread_t*)malloc(sizeof(memread_t));
+ mr->data = (unsigned char*)newdata;
+ mr->length = newlength;
+ r->read = reader_memread;
+ r->dealloc = reader_memread_dealloc;
+ r->internal = (void*)mr;
+ r->type = READER_TYPE_MEM;
+ r->mybyte = 0;
+ r->bitpos = 8;
+ r->pos = 0;
+}
+
+/* ---------------------------- mem writer ------------------------------- */
+
+typedef struct _memwrite
+{
+ unsigned char*data;
+ int length;
+} memwrite_t;
+
+static int writer_memwrite_write(writer_t*w, void* data, int len)
+{
+ memwrite_t*mw = (memwrite_t*)w->internal;
+ if(mw->length - w->pos > len) {
+ memcpy(&mw->data[w->pos], data, len);
+ w->pos += len;
+ return len;
+ } else {
+ memcpy(&mw->data[w->pos], data, mw->length - w->pos);
+ w->pos = mw->length;
+ return mw->length - w->pos;
+ }
+}
+static void writer_memwrite_finish(writer_t*w)
+{
+ if(w->internal)
+ free(w->internal);
+ w->internal = 0;
+}
+static void dummy_flush(writer_t*w)
+{
+}
+void writer_init_memwriter(writer_t*w, void*data, int len)
+{
+ memwrite_t *mr;
+ mr = (memwrite_t*)malloc(sizeof(memwrite_t));
+ mr->data = (unsigned char *)data;
+ mr->length = len;
+ memset(w, 0, sizeof(writer_t));
+ w->write = writer_memwrite_write;
+ w->flush = dummy_flush;
+ w->finish = writer_memwrite_finish;
+ w->internal = (void*)mr;
+ w->type = WRITER_TYPE_MEM;
+ w->bitpos = 0;
+ w->mybyte = 0;
+ w->pos = 0;
+}
+
+/* ------------------------- growing mem writer ------------------------------- */
+
+typedef struct _growmemwrite
+{
+ unsigned char*data;
+ int length;
+ U32 grow;
+} growmemwrite_t;
+static int writer_growmemwrite_write(writer_t*w, void* data, int len)
+{
+ growmemwrite_t*mw = (growmemwrite_t*)w->internal;
+ if(!mw->data) {
+ fprintf(stderr, "Illegal write operation: data already given away");
+ exit(1);
+ }
+ if(mw->length - w->pos < len) {
+ int newlength = mw->length;
+ while(newlength - w->pos < len) {
+ newlength += mw->grow;
+ }
+#ifdef NO_REALLOC
+ unsigned char*newmem = (unsigned char*)malloc(newlength);
+ memcpy(newmem, mw->data, mw->length);
+ free(mw->data);
+ mw->data = newmem;
+#else
+ mw->data = (unsigned char*)realloc(mw->data, newlength);
+#endif
+ mw->length = newlength;
+ }
+ memcpy(&mw->data[w->pos], data, len);
+ w->pos += len;
+ return len;
+}
+static void writer_growmemwrite_finish(writer_t*w)
+{
+ growmemwrite_t*mw = (growmemwrite_t*)w->internal;
+ if(mw->data) {
+ free(mw->data);mw->data = 0;
+ }
+ mw->length = 0;
+ free(w->internal);mw=0;
+ memset(w, 0, sizeof(writer_t));
+}
+void* writer_growmemwrite_memptr(writer_t*w, int*len)
+{
+ growmemwrite_t*mw = (growmemwrite_t*)w->internal;
+ if(len) {
+ *len = w->pos;
+ }
+ return mw->data;
+}
+void* writer_growmemwrite_getmem(writer_t*w)
+{
+ growmemwrite_t*mw = (growmemwrite_t*)w->internal;
+ void*ret = mw->data;
+ /* remove own reference so that neither write() nor finish() can free it.
+ It's property of the caller now.
+ */
+ mw->data = 0;
+ return ret;
+}
+void writer_growmemwrite_reset(writer_t*w)