Changeset: 85cd30b5e7f6 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=85cd30b5e7f6
Added Files:
        common/stream/text_stream.c
Modified Files:
        common/stream/Makefile.ag
        common/stream/stream.h
        common/stream/xz_stream.c
Branch: makelibstreamgreatagain
Log Message:

Add text_stream and use it in xz_stream

It does not convert line endings yet, but the bom conversions, which were 
broken by
the previous commit, work again.


diffs (172 lines):

diff --git a/common/stream/Makefile.ag b/common/stream/Makefile.ag
--- a/common/stream/Makefile.ag
+++ b/common/stream/Makefile.ag
@@ -24,7 +24,7 @@ lib_stream  =  {
                url_stream.c socket_stream.c \
                memio.c callback.c blackhole.c fwf.c \
                iconv_stream.c \
-               misc.c \
+               misc.c text_stream.c \
                stream.h stream_internal.h stream_socket.h
        VERSION = $(STREAM_VERSION)
        LIBS = WIN32?$(SOCKET_LIBS) \
diff --git a/common/stream/stream.h b/common/stream/stream.h
--- a/common/stream/stream.h
+++ b/common/stream/stream.h
@@ -272,4 +272,7 @@ stream_export stream *stream_blackhole_c
 
 stream_export stream *stream_fwf_create(stream *restrict s, size_t num_fields, 
size_t *restrict widths, char filler); // sql.c
 
+
+stream_export stream *create_text_stream(stream *s);
+
 #endif /*_STREAM_H_*/
diff --git a/common/stream/text_stream.c b/common/stream/text_stream.c
new file mode 100644
--- /dev/null
+++ b/common/stream/text_stream.c
@@ -0,0 +1,126 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0.  If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 1997 - July 2008 CWI, August 2008 - 2020 MonetDB B.V.
+ */
+
+#include "monetdb_config.h"
+#include "stream.h"
+#include "stream_internal.h"
+
+/* When reading, text streams convert \r\n to \n regardless of operating 
system,
+ * and they drop the leading UTF-8 BOM marker if found.
+ * When writing on Windows, \n is translated back to \r\n.
+ *
+ * Currently, skipping the BOM happens when opening
+ */
+
+#define UTF8BOM                "\xEF\xBB\xBF"  /* UTF-8 encoding of Unicode 
BOM */
+#define UTF8BOMLENGTH  3       /* length of above */
+
+
+typedef struct text_stream_state {
+       char putback_buf[UTF8BOMLENGTH];
+       int putback_start;
+       int putback_end;
+} state;
+
+
+static void
+text_destroy(stream *s)
+{
+       if (s == NULL)
+               return;
+
+       free(s->stream_data.p);
+       destroy_stream(s);
+}
+
+static ssize_t
+text_read(stream *restrict s, void *restrict buf, size_t elmsize, size_t cnt)
+{
+       return s->inner->read(s->inner, buf, elmsize, cnt);
+}
+
+static ssize_t
+text_read_putback(stream *restrict s, void *restrict buf, size_t elmsize, 
size_t cnt)
+{
+       state *st = (state*) s->stream_data.p;
+       char *p = buf;
+       size_t size = elmsize * cnt;
+       size_t i;
+
+       for (i = 0; i < size; i++) {
+               if (st->putback_start == st->putback_end) {
+                       s->read = text_read;
+                       break;
+               }
+               *p++ = st->putback_buf[st->putback_start++];
+       }
+
+       return i;
+}
+
+
+static ssize_t
+skip_bom(stream *s)
+{
+       state *st = (state*) s->stream_data.p;
+       stream *inner = s->inner;
+
+       ssize_t nread = mnstr_read(inner, st->putback_buf, 1, UTF8BOMLENGTH);
+       if (nread < 0)
+               return nread;
+
+       if (nread == UTF8BOMLENGTH &&  memcmp(st->putback_buf, UTF8BOM, nread) 
== 0) {
+               // Bingo! Skip it!
+               s->isutf8 = true;
+               return 3;
+       }
+
+
+       // We have consumed some bytes that have to be returned.
+       // skip_bom left them in the putback_buf.
+       // Switch to a read function that returns them.
+       s->read = text_read_putback;
+       st->putback_start = 0;
+       st->putback_end = nread;
+
+       return nread;
+}
+
+
+stream *
+create_text_stream(stream *inner)
+{
+       assert(inner->readonly);
+       state *st = malloc(sizeof(state));
+       struct stream *s = create_wrapper_stream(NULL, inner);
+       if (st == NULL)
+               goto bail;
+       if (s == NULL)
+               goto bail;
+
+       *st = (state) { .putback_start = 0, .putback_end = 0, };
+       s->stream_data.p = st;
+
+       s->binary = false;
+       s->destroy = text_destroy;
+
+       // bool isutf8;         /* known to be UTF-8 due to BOM */
+       // ssize_t (*read)(stream *restrict s, void *restrict buf, size_t 
elmsize, size_t cnt);
+       // ssize_t (*write)(stream *restrict s, const void *restrict buf, 
size_t elmsize, size_t cnt);
+       // void (*close)(stream *s);
+       // void (*destroy)(stream *s);
+       // int (*flush)(stream *s);
+
+       if (skip_bom(s) < 0)
+               goto bail;
+       return s;
+bail:
+       free(st);
+       destroy_stream(s);
+       return NULL;
+}
diff --git a/common/stream/xz_stream.c b/common/stream/xz_stream.c
--- a/common/stream/xz_stream.c
+++ b/common/stream/xz_stream.c
@@ -347,12 +347,8 @@ open_xzwstream(const char *restrict file
 stream *
 open_xzrastream(const char *filename)
 {
-       stream *s;
-
-       if ((s = open_xzstream(filename, "r")) == NULL)
-               return NULL;
-       s->binary = false;
-       return s;
+       stream *s = open_xzstream(filename, "r");
+       return create_text_stream(s);
 }
 
 stream *
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to