Stream Z-encoding seems to work now.
authorWilfried Goesgens <dothebart@citadel.org>
Sun, 30 Nov 2014 13:02:41 +0000 (14:02 +0100)
committerWilfried Goesgens <dothebart@citadel.org>
Sun, 30 Nov 2014 13:02:41 +0000 (14:02 +0100)
libcitadel/lib/libcitadel.c
libcitadel/lib/libcitadel.h
libcitadel/lib/stringbuf.c
libcitadel/tests/Makefile.in

index 29fe71d..51f0f1f 100644 (file)
@@ -48,6 +48,8 @@ ConstStr RoomNetCfgStrs[maxRoomNetCfg] = {
 
 extern int EnableSplice;
 extern int BaseStrBufSize;
+extern int ZLibCompressionRatio;
+
 char *libcitadel_version_string(void) {
        return "libcitadel(unnumbered)";
 }
@@ -58,11 +60,16 @@ int libcitadel_version_number(void) {
 
 void StartLibCitadel(size_t basesize)
 {
-       const char *Splice;
+       const char *envvar;
+
        BaseStrBufSize = basesize;
-       Splice = getenv("LIBCITADEL_ENABLE_SPLICE");
-       if (Splice != NULL)
-               EnableSplice = atol(Splice);
+       envvar = getenv("LIBCITADEL_ENABLE_SPLICE");
+       if (envvar != NULL)
+               EnableSplice = atol(envvar);
+
+       envvar = getenv("LIBCITADEL_ZLIB_LEVEL");
+       if (envvar != NULL)
+               ZLibCompressionRatio = atol(envvar);
 }
 
 void ShutDownLibCitadel(void)
index 7dd18e6..1486916 100644 (file)
@@ -339,12 +339,16 @@ void StrBuf_RFC822_2_Utf8(StrBuf *Target,
 void StrBuf_RFC822_to_Utf8(StrBuf *Target, const StrBuf *DecodeMe, const StrBuf* DefaultCharset, StrBuf *FoundCharset);
 
 typedef enum __eStreamType {
-       eBase64Decode
+       eBase64Encode,
+       eBase64Decode,
+       eZLibEncode,
+       eZLibDecode,
+       eEmtyCodec
 } eStreamType;
 
 void *StrBufNewStreamContext(eStreamType type);
 void StrBufDestroyStreamContext(eStreamType type, void **Stream);
-void StrBufStreamDecodeTo(StrBuf *Target, const StrBuf *In, const char* pIn, long pInLen, void *Stream);
+void StrBufStreamTranscode(eStreamType type, IOBuffer *Target, IOBuffer *In, const char* pIn, long pInLen, void *Stream, int LastChunk);
 
 int StrBufDecodeBase64(StrBuf *Buf);
 int StrBufDecodeBase64To(const StrBuf *BufIn, StrBuf *BufOut);
index 4368646..1171e99 100644 (file)
@@ -54,6 +54,12 @@ int ZEXPORT compress_gzip(Bytef * dest, size_t * destLen,
 #endif
 int BaseStrBufSize = 64;
 int EnableSplice = 0;
+int ZLibCompressionRatio = -1; /* defaults to 6 */
+#ifdef HAVE_ZLIB
+#define DEF_MEM_LEVEL 8 /*< memlevel??? */
+#define OS_CODE 0x03   /*< unix */
+const int gz_magic[2] = { 0x1f, 0x8b };        /* gzip magic header */
+#endif
 
 const char *StrBufNOTNULL = ((char*) NULL) - 1;
 
@@ -2848,6 +2854,11 @@ int StrBufDecodeBase64To(const StrBuf *BufIn, StrBuf *BufOut)
        return BufOut->BufUsed;
 }
 
+typedef struct __z_enc_stream {
+       StrBuf OutBuf;
+       z_stream zstream;
+} z_enc_stream;
+
 void *StrBufNewStreamContext(eStreamType type)
 {
        base64_decodestate *state;;
@@ -2855,47 +2866,265 @@ void *StrBufNewStreamContext(eStreamType type)
        switch (type)
        {
        case eBase64Decode:
+       case eBase64Encode:
                state = (base64_decodestate*) malloc(sizeof(base64_decodestate));
                base64_init_decodestate(state);
                return state;
+               break;
+       case eZLibDecode:
+       {
+/*
+               z_enc_stream *stream;
+               int err;
+
+               stream = (z_enc_stream *) malloc(sizeof(z_enc_stream));
+               memset(stream, 0, sizeof(z_enc_stream));
+               stream->OutBuf.BufSize = 64*SIZ;
+               stream->OutBuf.buf = (char*)malloc(stream->OutBuf.BufSize);
+
+               err = deflateInit(&stream->zstream,
+                                 ZLibCompressionRatio);
+
+               if (err != Z_OK)
+                       return NULL;/// tODO cleanup
+               return stream;
+*/
+       }
+       case eZLibEncode:
+       {
+               z_enc_stream *stream;
+               int err;
+
+               stream = (z_enc_stream *) malloc(sizeof(z_enc_stream));
+               memset(stream, 0, sizeof(z_enc_stream));
+               stream->OutBuf.BufSize = 4*SIZ; /// todo 64
+               stream->OutBuf.buf = (char*)malloc(stream->OutBuf.BufSize);
+               /* write gzip header * /
+               stream->OutBuf.BufUsed = snprintf
+                       (stream->OutBuf.buf,
+                        stream->OutBuf.BufSize, 
+                        "%c%c%c%c%c%c%c%c%c%c",
+                        gz_magic[0], gz_magic[1], Z_DEFLATED,
+                        0 /*flags * / , 0, 0, 0, 0 /*time * / , 0 /* xflags * / ,
+                        OS_CODE);
+/*
+               err = deflateInit2(&stream->zstream,
+                                  ZLibCompressionRatio,
+                                  Z_DEFLATED,
+                                  -MAX_WBITS,
+                                  DEF_MEM_LEVEL,
+                                  Z_DEFAULT_STRATEGY);
+*/
+               err = deflateInit(&stream->zstream,
+                                 ZLibCompressionRatio);
+
+               if (err != Z_OK)
+                       return NULL;/// tODO cleanup
+               return stream;
+       }
+       case eEmtyCodec:
+               /// TODO
+
                break;
        }
        return NULL;
 }
 
-void StrBufDestroyStreamContext(eStreamType type, void **Stream)
+void StrBufDestroyStreamContext(eStreamType type, void **vStream)
 {
        switch (type)
        {
+       case eBase64Encode:
        case eBase64Decode:
-               free(*Stream);
-               *Stream = NULL;
+               free(*vStream);
+               *vStream = NULL;
+               break;
+       case eZLibDecode:
+       case eZLibEncode:
+       {
+               z_enc_stream *stream = (z_enc_stream *)*vStream;
+               free(stream->OutBuf.buf);
+               free(stream);
+// todo more?
+               *vStream = NULL;
                break;
        }
+       case eEmtyCodec: 
+               break; /// TODO
+       }
 }
-void StrBufStreamDecodeTo(StrBuf *Target, const StrBuf *In, const char* pIn, long pInLen, void *Stream)
+
+void StrBufStreamTranscode(eStreamType type, IOBuffer *Target, IOBuffer *In, const char* pIn, long pInLen, void *vStream, int LastChunk)
 {
-       base64_decodestate *state = Stream;
-       long ExpectLen;
 
-       if (In != NULL)
+       switch (type)
+       {
+       case eBase64Encode:
        {
-               pIn = In->buf;
-               pInLen = In->BufUsed;
+               /// TODO
+/*
+               // base64_decodestate *state = (base64_decodestate*)vStream;
+               long ExpectLen;
+               
+               if (In != NULL)
+               {
+                       pIn = In->buf;
+                       pInLen = In->BufUsed;
+               }
+               if ((In == NULL) || (vStream == NULL))
+                       return;
+               
+               ExpectLen = (pInLen / 4) * 3;
+
+               if (Target->BufSize - Target->BufUsed < ExpectLen)
+               {
+                       IncreaseBuf(Target, 1, Target->BufUsed + ExpectLen + 1);
+               }
+
+               ////    ExpectLen = base64_encode_block(pIn, pInLen, Target->buf + Target->BufUsed, state);
+               Target->BufUsed += ExpectLen;
+               Target->buf[Target->BufUsed] = '\0';
+*/
        }
-       if ((pIn == NULL) || (Stream == NULL))
-               return;
-       
-       ExpectLen = (pInLen / 4) * 3;
+       break;
+       case eBase64Decode:
+       {
+/*
+               base64_decodestate *state = (base64_decodestate *)vStream;
+               long ExpectLen;
+               
+               if (In != NULL)
+               {
+                       pIn = In->buf;
+                       pInLen = In->BufUsed;
+               }
+               if ((pIn == NULL) || (vStream == NULL))
+                       return;
+               
+               ExpectLen = (pInLen / 4) * 3;
 
-       if (Target->BufSize - Target->BufUsed < ExpectLen)
+               if (Target->BufSize - Target->BufUsed < ExpectLen)
+               {
+                       IncreaseBuf(Target, 1, Target->BufUsed + ExpectLen + 1);
+               }
+
+               ExpectLen = base64_decode_block(pIn, pInLen, Target->buf + Target->BufUsed, state);
+               Target->BufUsed += ExpectLen;
+               Target->buf[Target->BufUsed] = '\0';
+*/
+       }
+       break;
+       case eZLibEncode:
        {
-               IncreaseBuf(Target, 1, Target->BufUsed + ExpectLen + 1);
+               z_enc_stream *stream = (z_enc_stream *)vStream;
+               int org_outbuf_len = stream->zstream.total_out;
+               int err;
+               unsigned int chunkavail;
+
+               if (In->ReadWritePointer != NULL)
+               {
+                       stream->zstream.next_in = (Bytef *) In->ReadWritePointer;
+                       stream->zstream.avail_in = (uInt) In->Buf->BufUsed - 
+                               (In->ReadWritePointer - In->Buf->buf);
+               }
+               else
+               {
+                       stream->zstream.next_in = (Bytef *) In->Buf->buf;
+                       stream->zstream.avail_in = (uInt) In->Buf->BufUsed;
+               }
+
+               stream->zstream.next_out = (unsigned char*)stream->OutBuf.buf + stream->OutBuf.BufUsed;
+               stream->zstream.avail_out = chunkavail = (uInt) stream->OutBuf.BufSize - stream->OutBuf.BufUsed;
+
+               err = deflate(&stream->zstream,  (LastChunk) ? Z_FINISH : Z_NO_FLUSH);
+
+               stream->OutBuf.BufUsed += (chunkavail - stream->zstream.avail_out);
+               /// todo + org_outbuf_len;
+
+               if (Target) SwapBuffers(Target->Buf, &stream->OutBuf);
+
+               if (stream->zstream.avail_in == 0)
+               {
+                       FlushStrBuf(In->Buf);
+                       In->ReadWritePointer = NULL;
+               }
+               else
+               {
+                       if (stream->zstream.avail_in < 64)
+                       {
+                               memmove(In->Buf->buf,
+                                       In->Buf->buf + In->Buf->BufUsed - stream->zstream.avail_in,
+                                       stream->zstream.avail_in);
+
+                               In->Buf->BufUsed = stream->zstream.avail_in;
+                               In->Buf->buf[In->Buf->BufUsed] = '\0';
+                       }
+                       else
+                       {
+                               
+                               In->ReadWritePointer = In->Buf->buf + 
+                                       (In->Buf->BufUsed - stream->zstream.avail_in);
+                       }
+               }
+
        }
+       break;
+       case eZLibDecode: {
+               z_enc_stream *stream = (z_enc_stream *)vStream;
+               int org_outbuf_len = stream->zstream.total_out;
+               int err;
+
+               if (In->ReadWritePointer != NULL)
+               {
+                       stream->zstream.next_in = (Bytef *) In->ReadWritePointer;
+                       stream->zstream.avail_in = (uInt) In->Buf->BufUsed - 
+                               (In->ReadWritePointer - In->Buf->buf);
+               }
+               else
+               {
+                       stream->zstream.next_in = (Bytef *) In->Buf->buf;
+                       stream->zstream.avail_in = (uInt) In->Buf->BufUsed;
+               }
+
+               stream->zstream.next_out = (unsigned char*)stream->OutBuf.buf + stream->OutBuf.BufUsed;
+               stream->zstream.avail_out = (uInt) stream->OutBuf.BufSize - stream->OutBuf.BufUsed;
+
+               err = deflate(&stream->zstream,  (LastChunk) ? Z_FINISH : Z_NO_FLUSH);
 
-       ExpectLen = base64_decode_block(pIn, pInLen, Target->buf + Target->BufUsed, state);
-       Target->BufUsed += ExpectLen;
-       Target->buf[Target->BufUsed] = '\0';
+               stream->OutBuf.BufUsed += stream->zstream.total_out + org_outbuf_len;
+
+               if (Target) SwapBuffers(Target->Buf, &stream->OutBuf);
+
+               if (stream->zstream.avail_in == 0)
+               {
+                       FlushStrBuf(In->Buf);
+                       In->ReadWritePointer = NULL;
+               }
+               else
+               {
+                       if (stream->zstream.avail_in < 64)
+                       {
+                               memmove(In->Buf->buf,
+                                       In->Buf->buf + In->Buf->BufUsed - stream->zstream.avail_in,
+                                       stream->zstream.avail_in);
+
+                               In->Buf->BufUsed = stream->zstream.avail_in;
+                               In->Buf->buf[In->Buf->BufUsed] = '\0';
+                       }
+                       else
+                       {
+                               
+                               In->ReadWritePointer = In->Buf->buf + 
+                                       (In->Buf->BufUsed - stream->zstream.avail_in);
+                       }
+               }
+       }
+               break;
+       case eEmtyCodec: {
+
+       }
+               break; /// TODO
+       }
 }
 
 /**
@@ -3899,10 +4128,6 @@ long StrBuf_Utf8StrCut(StrBuf *Buf, int maxlen)
  *                               wrapping ZLib                                 *
  *******************************************************************************/
 
-#ifdef HAVE_ZLIB
-#define DEF_MEM_LEVEL 8 /*< memlevel??? */
-#define OS_CODE 0x03   /*< unix */
-
 /**
  * @ingroup StrBuf_DeEnCoder
  * @brief uses the same calling syntax as compress2(), but it
@@ -3913,14 +4138,13 @@ long StrBuf_Utf8StrCut(StrBuf *Buf, int maxlen)
  * @param sourceLen length of source to encode 
  * @param level compression level
  */
+#ifdef HAVE_ZLIB
 int ZEXPORT compress_gzip(Bytef * dest,
                          size_t * destLen,
                          const Bytef * source,
                          uLong sourceLen,     
                          int level)
 {
-       const int gz_magic[2] = { 0x1f, 0x8b }; /* gzip magic header */
-
        /* write gzip header */
        snprintf((char *) dest, *destLen, 
                 "%c%c%c%c%c%c%c%c%c%c",
index 53732c7..5623396 100644 (file)
@@ -14,7 +14,16 @@ top_builddir=`pwd`
 
 # End of configuration section
 
-TARGETS=stringbuf_test stringbuf_IO_test stringbuf_conversion_test hashlist_test mimeparser_test mime_xdg_lookup_test wildfire_test stripallbut_test
+TARGETS=stringbuf_test \
+       stringbuf_IO_test \
+       stringbuf_conversion_test \
+       hashlist_test \
+       mimeparser_test \
+       mime_xdg_lookup_test \
+       wildfire_test \
+       stripallbut_test \
+       stringbuf_stream_test
+
 all: $(TARGETS)
 
 
@@ -40,6 +49,12 @@ stringbuf_IO_test:   $(LIBOBJS) stringbuf_IO_test.o
        ../.libs/libcitadel.a \
        -o stringbuf_IO_test
 
+stringbuf_stream_test: $(LIBOBJS) stringbuf_stream.o 
+       $(CC) $(LDFLAGS) $(LIBOBJS) $(LIBS) \
+       stringbuf_stream.o \
+       ../.libs/libcitadel.a \
+       -o stringbuf_stream_test
+
 stringbuf_conversion_test:     $(LIBOBJS) stringbuf_conversion.o 
        $(CC) $(LDFLAGS) $(LIBOBJS) $(LIBS) \
        stringbuf_conversion.o \