Update of /cvsroot/monetdb/MonetDB/src/common
In directory sc8-pr-cvs16.sourceforge.net:/tmp/cvs-serv12374
Modified Files:
stream.mx
Log Message:
Implemented an "iconv" stream: it takes a stream and an encoding as
input and produces a stream that converts utf-8 to the encoding when
writing and the encoding to utf-8 when reading. In other words, the
underlying stream uses the specified encoding and the "outside" uses
utf-8. This will be used by mclient to communicate to the outside
world.
Also added a bit of a hack to file streams: when the name starts with
a pipe symbol ("|"), the stream is closed using pclose instead of
fclose.
Added separators to the file to indicate different sections.
Index: stream.mx
===================================================================
RCS file: /cvsroot/monetdb/MonetDB/src/common/stream.mx,v
retrieving revision 1.150
retrieving revision 1.151
diff -u -d -r1.150 -r1.151
--- stream.mx 28 Nov 2007 14:54:32 -0000 1.150
+++ stream.mx 5 Dec 2007 13:44:18 -0000 1.151
@@ -169,6 +169,11 @@
stream_export stream *file_rastream(FILE *fp, const char *name);
stream_export stream *file_wastream(FILE *fp, const char *name);
+#ifdef HAVE_ICONV
+stream_export stream *iconv_rstream(stream *ss, const char *charset, const
char *name);
+stream_export stream *iconv_wstream(stream *ss, const char *charset, const
char *name);
+#endif
+
stream_export int rendezvous_streams(stream **in, stream **out, const char
*name);
typedef struct buffer {
@@ -689,6 +694,9 @@
return s;
}
+/* ------------------------------------------------------------------ */
+/* streams working on a disk file */
+
static ssize_t
file_read(stream *s, void *buf, size_t elmsize, size_t cnt)
{
@@ -723,9 +731,12 @@
if (!fp)
return;
- if (fp != stdin && fp != stdout && fp != stderr)
- fclose(fp);
- else if (s->access == ST_WRITE)
+ if (fp != stdin && fp != stdout && fp != stderr) {
+ if (s->name && *s->name == '|')
+ pclose(fp);
+ else
+ fclose(fp);
+ } else if (s->access == ST_WRITE)
fflush(fp);
s->stream_data.p = NULL;
}
@@ -811,6 +822,9 @@
return s;
}
+/* ------------------------------------------------------------------ */
+/* streams working on a gzip-compressed disk file */
+
#ifdef HAVE_LIBZ
static ssize_t
stream_gzread(stream *s, void *buf, size_t elmsize, size_t cnt)
@@ -935,6 +949,9 @@
}
#endif
+/* ------------------------------------------------------------------ */
+/* streams working on a bzip2-compressed disk file */
+
#ifdef HAVE_LIBBZ2
static ssize_t
stream_bzread(stream *s, void *buf, size_t elmsize, size_t cnt)
@@ -1056,6 +1073,9 @@
}
#endif
+/* ------------------------------------------------------------------ */
+/* streams working on a disk file, compressed or not */
+
stream *
open_rstream(const char *filename)
{
@@ -1230,6 +1250,9 @@
return open_wastream_(filename, "a");
}
+/* ------------------------------------------------------------------ */
+/* streams working on a remote file using cURL */
+
#ifdef HAVE_CURL
#include <curl/curl.h>
@@ -1441,6 +1464,9 @@
#endif /* HAVE_CURL */
+/* ------------------------------------------------------------------ */
+/* streams working on a socket */
+
static ssize_t
socket_write(stream *s, const void *buf, size_t elmsize, size_t cnt)
{
@@ -1666,6 +1692,9 @@
return s;
}
+/* ------------------------------------------------------------------ */
+/* streams working on a UDP socket */
+
typedef struct udp_stream {
SOCKET s;
struct sockaddr_in addr;
@@ -1829,6 +1858,9 @@
return s;
}
+/* ------------------------------------------------------------------ */
+/* streams working on a openSSL connection */
+
#ifdef HAVE_OPENSSL
struct ssl_data {
int error;
@@ -2106,6 +2138,9 @@
}
#endif /* HAVE_OPENSSL */
+/* ------------------------------------------------------------------ */
+/* streams working on an open file pointer */
+
static stream *
file_stream(const char *name)
{
@@ -2205,6 +2240,142 @@
return s;
}
+/* ------------------------------------------------------------------ */
+/* streams working on a substream, converting character sets using iconv */
+
+#ifdef HAVE_ICONV
+
+#ifdef HAVE_ICONV_H
+#include <iconv.h>
+#endif
+
+struct icstream {
+ iconv_t cd;
+ stream *s;
+ char buffer[BUFSIZ];
+ size_t buflen;
+};
+
+static ssize_t
+ic_write(stream *s, const void *buf, size_t elmsize, size_t cnt)
+{
+ struct icstream *ic = (struct icstream *) s->stream_data.p;
+ char *inbuf = (char *) buf;
+ size_t inbytesleft = elmsize * cnt;
+ char *outbuf = ic->buffer;
+ size_t outbytesleft = sizeof(ic->buffer);
+
+ while (inbytesleft > 0) {
+ iconv(ic->cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+ stream_write(ic->s, ic->buffer, 1, sizeof(ic->buffer) -
outbytesleft);
+ }
+ return cnt;
+}
+
+static ssize_t
+ic_read(stream *s, void *buf, size_t elmsize, size_t cnt)
+{
+ struct icstream *ic = (struct icstream *) s->stream_data.p;
+ char *inbuf = ic->buffer;
+ size_t inbytesleft = ic->buflen;
+ char *outbuf = (char *) buf;
+ size_t outbytesleft = elmsize * cnt;
+
+ errno = 0;
+ while (outbytesleft > 0 && errno != E2BIG) {
+ stream_read(ic->s, inbuf, 1, 1);
+ inbytesleft++;
+ iconv(ic->cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+ if (inbytesleft == 0)
+ inbuf = ic->buffer;
+ }
+ ic->buflen = inbytesleft;
+ return (elmsize * cnt - outbytesleft) / elmsize;
+}
+
+static void
+ic_close(stream *s)
+{
+ struct icstream *ic = (struct icstream *) s->stream_data.p;
+
+ if (ic == NULL)
+ return;
+ stream_close(ic->s);
+ free(s->stream_data.p);
+ s->stream_data.p = NULL;
+}
+
+static int
+ic_flush(stream *s)
+{
+ struct icstream *ic = (struct icstream *) s->stream_data.p;
+ char *outbuf = ic->buffer;
+ size_t outbytesleft = sizeof(ic->buffer);
+
+ iconv(ic->cd, NULL, NULL, &outbuf, &outbytesleft);
+ stream_write(ic->s, ic->buffer, 1, sizeof(ic->buffer) - outbytesleft);
+ stream_flush(ic->s);
+ return 1;
+}
+
+static stream *
+ic_open(iconv_t cd, stream *ss, const char *name)
+{
+ stream *s;
+ struct icstream *ic;
+
+ if ((s = create_stream(name)) == NULL)
+ return NULL;
+ s->read = ic_read;
+ s->write = ic_write;
+ s->close = ic_close;
+ s->flush = ic_flush;
+ s->stream_data.p = malloc(sizeof(struct icstream));
+ ic = (struct icstream *) s->stream_data.p;
+ ic->cd = cd;
+ ic->s = ss;
+ ic->buflen = 0;
+ return s;
+}
+
+stream *
+iconv_rstream(stream *ss, const char *charset, const char *name)
+{
+ stream *s;
+ iconv_t cd;
+
+#ifdef STREAM_DEBUG
+ printf("iconv_rstream %s %s\n", charset, name);
+#endif
+ cd = iconv_open(charset, "utf-8");
+ if (cd == (iconv_t) -1)
+ return NULL;
+ s = ic_open(cd, ss, name);
+ s->access = ST_READ;
+ return s;
+}
+
+stream *
+iconv_wstream(stream *ss, const char *charset, const char *name)
+{
+ stream *s;
+ iconv_t cd;
+
+#ifdef STREAM_DEBUG
+ printf("iconv_wstream %s %s\n", charset, name);
+#endif
+ cd = iconv_open("utf-8", charset);
+ if (cd == (iconv_t) -1)
+ return NULL;
+ s = ic_open(cd, ss, name);
+ s->access = ST_WRITE;
+ return s;
+}
+
+#endif /* HAVE_ICONV */
+
+/* ------------------------------------------------------------------ */
+
void
buffer_init(buffer *b, char *buf, size_t size)
{
@@ -2348,6 +2519,8 @@
return s;
}
+/* ------------------------------------------------------------------ */
+
/* A buffered stream consists of a sequence of blocks. Each block
consists of a count followed by the data in the block. A flush is
indicated by an empty block (i.e. just a count of 0).
@@ -2692,6 +2865,8 @@
return s->read == bs_read || s->write == bs_write;
}
+/* ------------------------------------------------------------------ */
+
ssize_t
stream_read_block(stream *s, void *buf, size_t elmsize, size_t cnt)
{
@@ -2855,6 +3030,8 @@
}
+/* ------------------------------------------------------------------ */
+
bstream *
bstream_create(stream *s, size_t size)
{
@@ -2988,6 +3165,8 @@
free(s);
}
+/* ------------------------------------------------------------------ */
+
/*
* Buffered write stream batches subsequent write requests in order to
optimize write bandwidth
*/
@@ -3063,6 +3242,8 @@
return ns;
}
+/* ------------------------------------------------------------------ */
+
#ifdef HAVE_PIPE
static ssize_t
pipe_write(stream *s, const void *buf, size_t elmsize, size_t cnt)
-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
Monetdb-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/monetdb-checkins