[gmime: 1/5] Rewrote GMimeFilterStrip to handle DOS line endings



commit c65a09b014e98af36b3a59a0eafc1364cc141857
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date:   Mon Mar 20 20:22:42 2017 -0400

    Rewrote GMimeFilterStrip to handle DOS line endings

 gmime/gmime-filter-strip.c |   89 +++++++++++++++++++++++++------------
 gmime/gmime-filter-strip.h |    2 +
 util/Makefile.am           |    2 +
 util/packed.c              |  105 ++++++++++++++++++++++++++++++++++++++++++++
 util/packed.h              |   47 ++++++++++++++++++++
 5 files changed, 217 insertions(+), 28 deletions(-)
---
diff --git a/gmime/gmime-filter-strip.c b/gmime/gmime-filter-strip.c
index e98a064..5b0c964 100644
--- a/gmime/gmime-filter-strip.c
+++ b/gmime/gmime-filter-strip.c
@@ -27,6 +27,8 @@
 #include <string.h>
 
 #include "gmime-filter-strip.h"
+#include "gmime-table-private.h"
+#include "packed.h"
 
 
 /**
@@ -99,12 +101,16 @@ g_mime_filter_strip_class_init (GMimeFilterStripClass *klass)
 static void
 g_mime_filter_strip_init (GMimeFilterStrip *filter, GMimeFilterStripClass *klass)
 {
-       /* no-op */
+       filter->lwsp = packed_byte_array_new ();
 }
 
 static void
 g_mime_filter_strip_finalize (GObject *object)
 {
+       GMimeFilterStrip *filter = (GMimeFilterStrip *) object;
+       
+       packed_byte_array_free (filter->lwsp);
+       
        G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -116,56 +122,83 @@ filter_copy (GMimeFilter *filter)
 }
 
 static void
-filter_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
-              char **out, size_t *outlen, size_t *outprespace)
+convert (GMimeFilter *filter, char *in, size_t len, size_t prespace,
+        char **out, size_t *outlen, size_t *outprespace, gboolean flush)
 {
-       register unsigned char *inptr, *last;
-       unsigned char *inend, *start;
-       char *outptr;
+       GMimeFilterStrip *strip = (GMimeFilterStrip *) filter;
+       PackedByteArray *lwsp = (PackedByteArray *) strip->lwsp;
+       register char *inptr, *outptr;
+       char *inend, *outbuf;
        
-       g_mime_filter_set_size (filter, len, FALSE);
+       if (len == 0) {
+               if (flush)
+                       packed_byte_array_clear (lwsp);
+               
+               *outprespace = prespace;
+               *outlen = len;
+               *out = in;
+               
+               return;
+       }
        
-       last = inptr = (unsigned char *) in;
-       inend = (unsigned char *) in + len;
+       g_mime_filter_set_size (filter, len + lwsp->len, FALSE);
+       outptr = outbuf = filter->outbuf;
+       inend = in + len;
+       inptr = in;
        
-       outptr = filter->outbuf;
+       if (flush)
+               packed_byte_array_clear (strip->lwsp);
        
        while (inptr < inend) {
-               start = inptr;
-               while (inptr < inend && *inptr != '\n') {
-                       if (*inptr != ' ' && *inptr != '\t')
-                               last = inptr + 1;
-                       inptr++;
+               if (is_blank (*inptr)) {
+                       packed_byte_array_add (lwsp, *inptr);
+               } else if (*inptr == '\r') {
+                       packed_byte_array_clear (lwsp);
+                       *outptr++ = *inptr;
+               } else if (*inptr == '\n') {
+                       packed_byte_array_clear (lwsp);
+                       *outptr++ = *inptr;
+               } else {
+                       if (lwsp->len > 0) {
+                               packed_byte_array_copy_to (lwsp, outptr);
+                               outptr += lwsp->len;
+                               packed_byte_array_clear (lwsp);
+                       }
+                       
+                       *outptr++ = *inptr;
                }
                
-               memcpy (outptr, start, last - start);
-               outptr += (last - start);
-               if (inptr < inend) {
-                       /* write the newline */
-                       *outptr++ = (char) *inptr++;
-                       last = inptr;
-               }
+               inptr++;
        }
        
-       g_mime_filter_backup (filter, (char *) last, inptr - last);
+       if (flush)
+               packed_byte_array_clear (lwsp);
        
-       *out = filter->outbuf;
-       *outlen = outptr - filter->outbuf;
        *outprespace = filter->outpre;
+       *outlen = (outptr - filter->outbuf);
+       *out = filter->outbuf;
+}
+
+static void
+filter_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
+              char **out, size_t *outlen, size_t *outprespace)
+{
+       convert (filter, in, len, prespace, out, outlen, outprespace, FALSE);
 }
 
 static void 
 filter_complete (GMimeFilter *filter, char *in, size_t len, size_t prespace,
                 char **out, size_t *outlen, size_t *outprespace)
 {
-       if (len)
-               filter_filter (filter, in, len, prespace, out, outlen, outprespace);
+       convert (filter, in, len, prespace, out, outlen, outprespace, TRUE);
 }
 
 static void
 filter_reset (GMimeFilter *filter)
 {
-       /* no-op */
+       GMimeFilterStrip *strip = (GMimeFilterStrip *) filter;
+       
+       packed_byte_array_clear (strip->lwsp);
 }
 
 
diff --git a/gmime/gmime-filter-strip.h b/gmime/gmime-filter-strip.h
index 6e9151b..fd64174 100644
--- a/gmime/gmime-filter-strip.h
+++ b/gmime/gmime-filter-strip.h
@@ -45,6 +45,8 @@ typedef struct _GMimeFilterStripClass GMimeFilterStripClass;
 struct _GMimeFilterStrip {
        GMimeFilter parent_object;
        
+       /* < private > */
+       void *lwsp;
 };
 
 struct _GMimeFilterStripClass {
diff --git a/util/Makefile.am b/util/Makefile.am
index cedddca..37535c4 100644
--- a/util/Makefile.am
+++ b/util/Makefile.am
@@ -19,6 +19,8 @@ libutil_la_SOURCES =                  \
        list.h                          \
        md5-utils.c                     \
        md5-utils.h                     \
+       packed.c                        \
+       packed.h                        \
        url-scanner.c                   \
        url-scanner.h
 
diff --git a/util/packed.c b/util/packed.c
new file mode 100644
index 0000000..187f26c
--- /dev/null
+++ b/util/packed.c
@@ -0,0 +1,105 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*  GMime
+ *  Copyright (C) 2000-2017 Jeffrey Stedfast
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "packed.h"
+
+
+PackedByteArray *
+packed_byte_array_new (void)
+{
+       PackedByteArray *packed;
+       
+       packed = g_slice_new (PackedByteArray);
+       packed->buffer = g_malloc (sizeof (guint16) * 64);
+       packed->allocated = 64;
+       packed->cur = -1;
+       packed->len = 0;
+}
+
+
+void
+packed_byte_array_free (PackedByteArray *packed)
+{
+       g_free (packed->buffer);
+       g_slice_free (PackedByteArray, packed);
+}
+
+
+void
+packed_byte_array_clear (PackedByteArray *packed)
+{
+       packed->cur = -1;
+       packed->len = 0;
+}
+
+
+static guint16 *
+ensure_buffer_size (PackedByteArray *packed, int size)
+{
+       if (packed->allocated > size)
+               return packed->buffer;
+       
+       size_t ideal = (size + 63) & ~63;
+       
+       packed->buffer = g_realloc (packed->buffer, sizeof (guint16) * ideal);
+       packed->allocated = ideal;
+       
+       return packed->buffer;
+}
+
+
+void
+packed_byte_array_add (PackedByteArray *packed, char c)
+{
+       guint16 *buffer = packed->buffer;
+        int cur = packed->cur;
+       
+       if (cur < 0 || c != (char) (buffer[cur] & 0xff) || (buffer[cur] & 0xff00) == 0xff00) {
+               buffer = ensure_buffer_size (packed, cur  + 2);
+               buffer[++cur] = (guint16) ((1 << 8) | (unsigned char) c);
+       } else {
+               buffer[cur] += (1 << 8);
+       }
+       
+       packed->cur = cur;
+       packed->len++;
+}
+
+
+void
+packed_byte_array_copy_to (PackedByteArray *packed, char *outbuf)
+{
+       register char *outptr = outbuf;
+       int count, i, n;
+       char c;
+       
+       for (i = 0; i <= packed->cur; i++) {
+               count = (packed->buffer[i] >> 8) & 0xff;
+               c = (char) (packed->buffer[i] & 0xff);
+               
+               for (n = 0; n < count; n++)
+                       *outptr++ = c;
+       }
+}
diff --git a/util/packed.h b/util/packed.h
new file mode 100644
index 0000000..f7a8b2c
--- /dev/null
+++ b/util/packed.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*  GMime
+ *  Copyright (C) 2000-2017 Jeffrey Stedfast
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+
+#ifndef __PACKED_BYTE_ARRAY_H__
+#define __PACKED_BYTE_ARRAY_H__
+
+#include <glib.h>
+#include <sys/types.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+       guint16 *buffer;
+       int allocated;
+       int cur, len;
+} PackedByteArray;
+
+G_GNUC_INTERNAL PackedByteArray *packed_byte_array_new (void);
+G_GNUC_INTERNAL void packed_byte_array_free (PackedByteArray *packed);
+
+G_GNUC_INTERNAL void packed_byte_array_clear (PackedByteArray *packed);
+
+G_GNUC_INTERNAL void packed_byte_array_add (PackedByteArray *packed, char c);
+
+G_GNUC_INTERNAL void packed_byte_array_copy_to (PackedByteArray *packed, char *outbuf);
+
+G_END_DECLS
+
+#endif /* __PACKED_BYTE_ARRAY_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]