From: Mark H Weaver <mhw@netris.org>
To: Andy Wingo <wingo@pobox.com>
Cc: "Ludovic Courtès" <ludo@gnu.org>, guile-devel@gnu.org
Subject: [PATCH] Add private port structure, and move iconv descriptors there
Date: Wed, 27 Mar 2013 16:00:55 -0400 [thread overview]
Message-ID: <87d2uk62a0.fsf_-_@tines.lan> (raw)
In-Reply-To: <87d2vdekws.fsf@tines.lan> (Mark H. Weaver's message of "Tue, 05 Mar 2013 13:55:31 -0500")
[-- Attachment #1: Type: text/plain, Size: 315 bytes --]
Hello all,
Here's a patch to add a private port structure. I moved both input_cd
and output_cd there. I plan to create more patches on top of this very
soon (BOM handling, more efficient per-port read options, maybe better
EOF handling), so a prompt review would be very helpful.
What do you think?
Mark
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: [PATCH] Add private port structure, and move the iconv descriptors there --]
[-- Type: text/x-diff, Size: 12442 bytes --]
From 47aadc79423200b226d7592ea6bbeb788f1c5bef Mon Sep 17 00:00:00 2001
From: Mark H Weaver <mhw@netris.org>
Date: Wed, 27 Mar 2013 15:41:45 -0400
Subject: [PATCH] Add private port structure, and move the iconv descriptors
there.
* libguile/private-ports.h: New file.
* libguile/Makefile.am (noinst_HEADERS): Add private-ports.h.
* libguile/ports.h (scm_t_port): Replace 'input_cd' and 'output_cd'
fields with 'internal' and 'reserved_for_future_use'.
* libguile/ports.c: Include private-ports.h.
(finalize_port, scm_i_remove_port, get_iconv_codepoint): Access
'input_cd' and 'output_cd' via 'internal' pointer.
(scm_new_port_table_entry): Initialize new internal fields.
Access 'input_cd' and 'output_cd' via 'internal' pointer.
(get_codepoint): Use 'internal->encoding_type' to detect if the
encoders are initialized and which encoding method to use.
(scm_i_set_port_encoding_x): Set the 'internal->encoding_type' field
appropriately. Access 'input_cd' and 'output_cd' via 'internal'
pointer.
* libguile/print.c: Include private-ports.h.
(display_string_using_iconv): Access 'input_cd' and 'output_cd' via
'internal' pointer.
(display_string): Use 'internal->encoding_type' to detect if the
encoders are initialized and which encoding method to use.
---
libguile/Makefile.am | 2 +-
libguile/ports.c | 79 +++++++++++++++++++++++++++++++---------------
libguile/ports.h | 7 ++--
libguile/print.c | 26 +++++++++------
libguile/private-ports.h | 41 ++++++++++++++++++++++++
5 files changed, 116 insertions(+), 39 deletions(-)
create mode 100644 libguile/private-ports.h
diff --git a/libguile/Makefile.am b/libguile/Makefile.am
index 4b1f96b..6eaca76 100644
--- a/libguile/Makefile.am
+++ b/libguile/Makefile.am
@@ -455,7 +455,7 @@ noinst_HEADERS = conv-integer.i.c conv-uinteger.i.c \
srfi-14.i.c \
quicksort.i.c \
win32-uname.h \
- private-gc.h private-options.h
+ private-gc.h private-options.h private-ports.h
# vm instructions
noinst_HEADERS += vm-engine.c vm-i-system.c vm-i-scheme.c vm-i-loader.c
diff --git a/libguile/ports.c b/libguile/ports.c
index 8737a76..45e770d 100644
--- a/libguile/ports.c
+++ b/libguile/ports.c
@@ -60,6 +60,8 @@
#include "libguile/fluids.h"
#include "libguile/eq.h"
+#include "libguile/private-ports.h"
+
#ifdef HAVE_STRING_H
#include <string.h>
#endif
@@ -589,10 +591,10 @@ finalize_port (void *ptr, void *data)
entry = SCM_PTAB_ENTRY (port);
- if (entry->input_cd != (iconv_t) -1)
- iconv_close (entry->input_cd);
- if (entry->output_cd != (iconv_t) -1)
- iconv_close (entry->output_cd);
+ if (entry->internal->input_cd != (iconv_t) -1)
+ iconv_close (entry->internal->input_cd);
+ if (entry->internal->output_cd != (iconv_t) -1)
+ iconv_close (entry->internal->output_cd);
SCM_SETSTREAM (port, 0);
SCM_CLR_PORT_OPEN_FLAG (port);
@@ -629,9 +631,15 @@ scm_new_port_table_entry (scm_t_bits tag)
enc = scm_i_default_port_encoding ();
entry->encoding = enc ? scm_gc_strdup (enc, "port") : NULL;
+ /* Initialize private fields. */
+ entry->reserved_for_future_use = NULL;
+ entry->internal = (struct scm_t_port_private *)
+ scm_gc_calloc (sizeof (struct scm_t_port_private), "port-private");
+ entry->internal->encoding_type = SCM_PORT_ENCODING_TYPE_UNINITIALIZED;
+
/* The conversion descriptors will be opened lazily. */
- entry->input_cd = (iconv_t) -1;
- entry->output_cd = (iconv_t) -1;
+ entry->internal->input_cd = (iconv_t) -1;
+ entry->internal->output_cd = (iconv_t) -1;
entry->ilseq_handler = scm_i_default_port_conversion_handler ();
@@ -686,18 +694,20 @@ scm_i_remove_port (SCM port)
p->putback_buf = NULL;
p->putback_buf_size = 0;
- if (p->input_cd != (iconv_t) -1)
+ if (p->internal->input_cd != (iconv_t) -1)
{
- iconv_close (p->input_cd);
- p->input_cd = (iconv_t) -1;
+ iconv_close (p->internal->input_cd);
+ p->internal->input_cd = (iconv_t) -1;
}
- if (p->output_cd != (iconv_t) -1)
+ if (p->internal->output_cd != (iconv_t) -1)
{
- iconv_close (p->output_cd);
- p->output_cd = (iconv_t) -1;
+ iconv_close (p->internal->output_cd);
+ p->internal->output_cd = (iconv_t) -1;
}
+ p->internal = NULL;
+
SCM_SETPTAB_ENTRY (port, 0);
scm_hashq_remove_x (scm_i_port_weak_hash, port);
@@ -1297,12 +1307,14 @@ get_iconv_codepoint (SCM port, scm_t_wchar *codepoint,
char buf[SCM_MBCHAR_BUF_SIZE], size_t *len)
{
scm_t_port *pt;
+ struct scm_t_port_private *pti;
int err, byte_read;
size_t bytes_consumed, output_size;
char *output;
scm_t_uint8 utf8_buf[SCM_MBCHAR_BUF_SIZE];
pt = SCM_PTAB_ENTRY (port);
+ pti = pt->internal;
for (output_size = 0, output = (char *) utf8_buf,
bytes_consumed = 0, err = 0;
@@ -1332,7 +1344,7 @@ get_iconv_codepoint (SCM port, scm_t_wchar *codepoint,
input_left = bytes_consumed + 1;
output_left = sizeof (utf8_buf);
- done = iconv (pt->input_cd, &input, &input_left,
+ done = iconv (pti->input_cd, &input, &input_left,
&output, &output_left);
if (done == (size_t) -1)
{
@@ -1369,15 +1381,22 @@ get_codepoint (SCM port, scm_t_wchar *codepoint,
int err;
scm_t_port *pt = SCM_PTAB_ENTRY (port);
- if (pt->input_cd == (iconv_t) -1)
+ if (pt->internal->encoding_type == SCM_PORT_ENCODING_TYPE_UNINITIALIZED)
/* Initialize the conversion descriptors, if needed. */
scm_i_set_port_encoding_x (port, pt->encoding);
- /* FIXME: In 2.1, add a flag to determine whether a port is UTF-8. */
- if (pt->input_cd == (iconv_t) -1)
- err = get_utf8_codepoint (port, codepoint, (scm_t_uint8 *) buf, len);
- else
- err = get_iconv_codepoint (port, codepoint, buf, len);
+ switch (pt->internal->encoding_type)
+ {
+ case SCM_PORT_ENCODING_TYPE_ICONV:
+ err = get_iconv_codepoint (port, codepoint, buf, len);
+ break;
+ case SCM_PORT_ENCODING_TYPE_UTF8:
+ err = get_utf8_codepoint (port, codepoint, (scm_t_uint8 *) buf, len);
+ break;
+ case SCM_PORT_ENCODING_TYPE_UNINITIALIZED:
+ default:
+ scm_syserror ("get_codepoint");
+ }
if (SCM_LIKELY (err == 0))
update_port_lf (*codepoint, port);
@@ -2208,13 +2227,16 @@ void
scm_i_set_port_encoding_x (SCM port, const char *encoding)
{
scm_t_port *pt;
+ struct scm_t_port_private *pti;
iconv_t new_input_cd, new_output_cd;
+ enum scm_t_port_encoding_type new_encoding_type;
new_input_cd = (iconv_t) -1;
new_output_cd = (iconv_t) -1;
/* Set the character encoding for this port. */
pt = SCM_PTAB_ENTRY (port);
+ pti = pt->internal;
if (encoding == NULL)
encoding = "ISO-8859-1";
@@ -2225,8 +2247,12 @@ scm_i_set_port_encoding_x (SCM port, const char *encoding)
/* If ENCODING is UTF-8, then no conversion descriptor is opened
because we do I/O ourselves. This saves 100+ KiB for each
descriptor. */
- if (strcmp (encoding, "UTF-8"))
+ if (!strcmp (encoding, "UTF-8"))
+ new_encoding_type = SCM_PORT_ENCODING_TYPE_UTF8;
+ else
{
+ new_encoding_type = SCM_PORT_ENCODING_TYPE_ICONV;
+
if (SCM_CELL_WORD_0 (port) & SCM_RDNG)
{
/* Open an input iconv conversion descriptor, from ENCODING
@@ -2251,13 +2277,14 @@ scm_i_set_port_encoding_x (SCM port, const char *encoding)
}
}
- if (pt->input_cd != (iconv_t) -1)
- iconv_close (pt->input_cd);
- if (pt->output_cd != (iconv_t) -1)
- iconv_close (pt->output_cd);
+ if (pti->input_cd != (iconv_t) -1)
+ iconv_close (pti->input_cd);
+ if (pti->output_cd != (iconv_t) -1)
+ iconv_close (pti->output_cd);
- pt->input_cd = new_input_cd;
- pt->output_cd = new_output_cd;
+ pti->input_cd = new_input_cd;
+ pti->output_cd = new_output_cd;
+ pti->encoding_type = new_encoding_type;
return;
diff --git a/libguile/ports.h b/libguile/ports.h
index d4d59b7..8aa29ee 100644
--- a/libguile/ports.h
+++ b/libguile/ports.h
@@ -43,6 +43,8 @@ typedef enum scm_t_port_rw_active {
SCM_PORT_WRITE = 2
} scm_t_port_rw_active;
+struct scm_t_port_private;
+
/* C representation of a Scheme port. */
typedef struct
@@ -112,9 +114,8 @@ typedef struct
unsigned char *putback_buf;
size_t putback_buf_size; /* allocated size of putback_buf. */
- /* input/output iconv conversion descriptors */
- void *input_cd;
- void *output_cd;
+ struct scm_t_port_private *internal;
+ void *reserved_for_future_use;
} scm_t_port;
diff --git a/libguile/print.c b/libguile/print.c
index 647eed8..51f9f01 100644
--- a/libguile/print.c
+++ b/libguile/print.c
@@ -56,6 +56,7 @@
#include "libguile/print.h"
#include "libguile/private-options.h"
+#include "libguile/private-ports.h"
\f
@@ -880,8 +881,10 @@ display_string_using_iconv (const void *str, int narrow_p, size_t len,
{
size_t printed;
scm_t_port *pt;
+ struct scm_t_port_private *pti;
pt = SCM_PTAB_ENTRY (port);
+ pti = pt->internal;
printed = 0;
@@ -910,7 +913,7 @@ display_string_using_iconv (const void *str, int narrow_p, size_t len,
output = encoded_output;
output_left = sizeof (encoded_output);
- done = iconv (pt->output_cd, &input, &input_left,
+ done = iconv (pti->output_cd, &input, &input_left,
&output, &output_left);
output_len = sizeof (encoded_output) - output_left;
@@ -920,7 +923,7 @@ display_string_using_iconv (const void *str, int narrow_p, size_t len,
int errno_save = errno;
/* Reset the `iconv' state. */
- iconv (pt->output_cd, NULL, NULL, NULL, NULL);
+ iconv (pti->output_cd, NULL, NULL, NULL, NULL);
/* Print the OUTPUT_LEN bytes successfully converted. */
scm_lfwrite (encoded_output, output_len, port);
@@ -984,16 +987,21 @@ display_string (const void *str, int narrow_p,
pt = SCM_PTAB_ENTRY (port);
- if (pt->output_cd == (iconv_t) -1)
+ if (pt->internal->encoding_type == SCM_PORT_ENCODING_TYPE_UNINITIALIZED)
/* Initialize the conversion descriptors, if needed. */
scm_i_set_port_encoding_x (port, pt->encoding);
- /* FIXME: In 2.1, add a flag to determine whether a port is UTF-8. */
- if (pt->output_cd == (iconv_t) -1)
- return display_string_as_utf8 (str, narrow_p, len, port);
- else
- return display_string_using_iconv (str, narrow_p, len,
- port, strategy);
+ switch (pt->internal->encoding_type)
+ {
+ case SCM_PORT_ENCODING_TYPE_ICONV:
+ return display_string_using_iconv (str, narrow_p, len,
+ port, strategy);
+ case SCM_PORT_ENCODING_TYPE_UTF8:
+ return display_string_as_utf8 (str, narrow_p, len, port);
+ case SCM_PORT_ENCODING_TYPE_UNINITIALIZED:
+ default:
+ scm_syserror ("display_string");
+ }
}
/* Attempt to display CH to PORT according to STRATEGY. Return non-zero
diff --git a/libguile/private-ports.h b/libguile/private-ports.h
new file mode 100644
index 0000000..369c4a5
--- /dev/null
+++ b/libguile/private-ports.h
@@ -0,0 +1,41 @@
+/*
+ * private-ports.h - private declarations for ports.
+ *
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * 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 3 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef SCM_PRIVATE_PORTS
+#define SCM_PRIVATE_PORTS
+
+#include "libguile/_scm.h"
+#include "libguile/ports.h"
+
+enum scm_t_port_encoding_type {
+ SCM_PORT_ENCODING_TYPE_UNINITIALIZED = 0,
+ SCM_PORT_ENCODING_TYPE_ICONV = 1,
+ SCM_PORT_ENCODING_TYPE_UTF8 = 2
+};
+
+struct scm_t_port_private
+{
+ enum scm_t_port_encoding_type encoding_type;
+ void *input_cd;
+ void *output_cd;
+};
+
+#endif
--
1.7.10.4
next prev parent reply other threads:[~2013-03-27 20:00 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-02-24 11:39 always O_BINARY? Andy Wingo
2013-02-24 12:08 ` Neil Jerram
2013-02-24 16:55 ` Mike Gran
2013-02-24 21:17 ` Ludovic Courtès
2013-02-28 3:24 ` Adding new information to scm_t_port (was Re: always O_BINARY?) Mark H Weaver
2013-02-28 8:53 ` Andy Wingo
2013-02-28 11:04 ` Ludovic Courtès
2013-02-28 13:09 ` Andy Wingo
2013-03-01 9:03 ` Ludovic Courtès
2013-03-05 18:55 ` Mark H Weaver
2013-03-27 20:00 ` Mark H Weaver [this message]
2013-03-27 20:28 ` [PATCH] Add private port structure, and move iconv descriptors there Ludovic Courtès
2013-03-27 20:51 ` Andy Wingo
2013-03-27 21:11 ` Mark H Weaver
2013-03-31 7:52 ` [PATCH] Add internal-only port structure; " Mark H Weaver
2013-03-31 13:20 ` Ludovic Courtès
2013-03-31 15:23 ` Mark H Weaver
2013-03-31 22:06 ` Ludovic Courtès
2013-04-01 18:57 ` Andy Wingo
2013-04-01 20:03 ` Mark H Weaver
2013-04-01 20:54 ` Andy Wingo
2013-04-01 21:04 ` Andy Wingo
2013-03-31 19:44 ` [PATCH] Add private port structure, and " Mark H Weaver
2013-03-31 22:08 ` Ludovic Courtès
2013-04-01 19:04 ` Andy Wingo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/guile/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87d2uk62a0.fsf_-_@tines.lan \
--to=mhw@netris.org \
--cc=guile-devel@gnu.org \
--cc=ludo@gnu.org \
--cc=wingo@pobox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).