[RFA 05/22] Turn wchar iterator into a class

Tom Tromey
2016-09-27T04:47:34Z

This changes wchar_iterator from charset.c into a real C++ class, then
updates the users to use the class. This lets us remove some cleanups
in favor of the class' destructor.

2016-09-26 Tom Tromey <tom@tromey.com>

* valprint.c (generic_emit_char, count_next_character)
(generic_printstr): Update.
* charset.c (struct wchar_iterator): Move to charset.h.
(wchar_iterator::wchar_iterator): Rename from
make_wchar_iterator, turn into a constructor.
(wchar_iterator::~wchar_iterator): Rename from
do_cleanup_iterator, turn into a destructor.
(make_cleanup_wchar_iterator): Remove.
(wchar_iterator::iterate): Rename from wchar_iterate. Remove
"iter" argument. Update.
* charset.h: Include <vector>.
(class wchar_iterator): New class, from old struct
wchar_iterator.
(make_wchar_iterator, make_cleanup_wchar_iterator): Don't
declare.
---
gdb/ChangeLog | 18 ++++++++++
gdb/charset.c | 106 +++++++++++++++++----------------------------------------
gdb/charset.h | 95 +++++++++++++++++++++++++++++----------------------
gdb/valprint.c | 25 ++++++--------
4 files changed, 114 insertions(+), 130 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 42c432d..b73b26e 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,23 @@
2016-09-26 Tom Tromey <tom@tromey.com>

+ * valprint.c (generic_emit_char, count_next_character)
+ (generic_printstr): Update.
+ * charset.c (struct wchar_iterator): Move to charset.h.
+ (wchar_iterator::wchar_iterator): Rename from
+ make_wchar_iterator, turn into a constructor.
+ (wchar_iterator::~wchar_iterator): Rename from
+ do_cleanup_iterator, turn into a destructor.
+ (make_cleanup_wchar_iterator): Remove.
+ (wchar_iterator::iterate): Rename from wchar_iterate. Remove
+ "iter" argument. Update.
+ * charset.h: Include <vector>.
+ (class wchar_iterator): New class, from old struct
+ wchar_iterator.
+ (make_wchar_iterator, make_cleanup_wchar_iterator): Don't
+ declare.
+
+2016-09-26 Tom Tromey <tom@tromey.com>
+
* top.c (new_ui_command, wait_sync_command_done)
(gdb_readline_wrapper): Use scoped_restore.
* infrun.c (fetch_inferior_event): Use scoped_restore.
diff --git a/gdb/charset.c b/gdb/charset.c
index abad901..66de30e 100644
--- a/gdb/charset.c
+++ b/gdb/charset.c
@@ -589,71 +589,30 @@ convert_between_encodings (const char *from, const char *to,

\f

-/* An iterator that returns host wchar_t's from a target string. */
-struct wchar_iterator
-{
- /* The underlying iconv descriptor. */
- iconv_t desc;
-
- /* The input string. This is updated as convert characters. */
- const gdb_byte *input;
- /* The number of bytes remaining in the input. */
- size_t bytes;
-
- /* The width of an input character. */
- size_t width;
-
- /* The output buffer and its size. */
- gdb_wchar_t *out;
- size_t out_size;
-};
-
/* Create a new iterator. */
-struct wchar_iterator *
-make_wchar_iterator (const gdb_byte *input, size_t bytes,
- const char *charset, size_t width)
+wchar_iterator::wchar_iterator (const gdb_byte *input, size_t bytes,
+ const char *charset, size_t width)
+: input (input),
+ bytes (bytes),
+ width (width),
+ out (1)
{
- struct wchar_iterator *result;
- iconv_t desc;
-
desc = iconv_open (INTERMEDIATE_ENCODING, charset);
if (desc == (iconv_t) -1)
perror_with_name (_("Converting character sets"));
-
- result = XNEW (struct wchar_iterator);
- result->desc = desc;
- result->input = input;
- result->bytes = bytes;
- result->width = width;
-
- result->out = XNEW (gdb_wchar_t);
- result->out_size = 1;
-
- return result;
}

-static void
-do_cleanup_iterator (void *p)
+wchar_iterator::~wchar_iterator ()
{
- struct wchar_iterator *iter = (struct wchar_iterator *) p;
-
- iconv_close (iter->desc);
- xfree (iter->out);
- xfree (iter);
-}
-
-struct cleanup *
-make_cleanup_wchar_iterator (struct wchar_iterator *iter)
-{
- return make_cleanup (do_cleanup_iterator, iter);
+ if (desc != (iconv_t) -1)
+ iconv_close (desc);
}

int
-wchar_iterate (struct wchar_iterator *iter,
- enum wchar_iterate_result *out_result,
- gdb_wchar_t **out_chars,
- const gdb_byte **ptr,
- size_t *len)
+wchar_iterator::iterate (enum wchar_iterate_result *out_result,
+ gdb_wchar_t **out_chars,
+ const gdb_byte **ptr,
+ size_t *len)
{
size_t out_request;

@@ -663,17 +622,17 @@ wchar_iterate (struct wchar_iterator *iter,
invalid input sequence -- but we want to reliably report this to
our caller so it can emit an escape sequence. */
out_request = 1;
- while (iter->bytes > 0)
+ while (bytes > 0)
{
- ICONV_CONST char *inptr = (ICONV_CONST char *) iter->input;
- char *outptr = (char *) &iter->out[0];
- const gdb_byte *orig_inptr = iter->input;
- size_t orig_in = iter->bytes;
+ ICONV_CONST char *inptr = (ICONV_CONST char *) input;
+ char *outptr = (char *) out.data ();
+ const gdb_byte *orig_inptr = input;
+ size_t orig_in = bytes;
size_t out_avail = out_request * sizeof (gdb_wchar_t);
size_t num;
- size_t r = iconv (iter->desc, &inptr, &iter->bytes, &outptr, &out_avail);
+ size_t r = iconv (desc, &inptr, &bytes, &outptr, &out_avail);

- iter->input = (gdb_byte *) inptr;
+ input = (gdb_byte *) inptr;

if (r == (size_t) -1)
{
@@ -688,10 +647,10 @@ wchar_iterate (struct wchar_iterator *iter,
/* Otherwise skip the first invalid character, and let
the caller know about it. */
*out_result = wchar_iterate_invalid;
- *ptr = iter->input;
- *len = iter->width;
- iter->input += iter->width;
- iter->bytes -= iter->width;
+ *ptr = input;
+ *len = width;
+ input += width;
+ bytes -= width;
return 0;

case E2BIG:
@@ -702,20 +661,17 @@ wchar_iterate (struct wchar_iterator *iter,
break;

++out_request;
- if (out_request > iter->out_size)
- {
- iter->out_size = out_request;
- iter->out = XRESIZEVEC (gdb_wchar_t, iter->out, out_request);
- }
+ if (out_request > out.size ())
+ out.reserve (out_request);
continue;

case EINVAL:
/* Incomplete input sequence. Let the caller know, and
arrange for future calls to see EOF. */
*out_result = wchar_iterate_incomplete;
- *ptr = iter->input;
- *len = iter->bytes;
- iter->bytes = 0;
+ *ptr = input;
+ *len = bytes;
+ bytes = 0;
return 0;

default:
@@ -727,9 +683,9 @@ wchar_iterate (struct wchar_iterator *iter,
/* We converted something. */
num = out_request - out_avail / sizeof (gdb_wchar_t);
*out_result = wchar_iterate_ok;
- *out_chars = iter->out;
+ *out_chars = out.data ();
*ptr = orig_inptr;
- *len = orig_in - iter->bytes;
+ *len = orig_in - bytes;
return num;
}

diff --git a/gdb/charset.h b/gdb/charset.h
index 559b328..891024c 100644
--- a/gdb/charset.h
+++ b/gdb/charset.h
@@ -19,6 +19,8 @@
#ifndef CHARSET_H
#define CHARSET_H

+#include <vector>
+
/* If the target program uses a different character set than the host,
GDB has some support for translating between the two; GDB converts
characters and strings to the host character set before displaying
@@ -81,54 +83,67 @@ enum wchar_iterate_result
wchar_iterate_eof
};

-/* Declaration of the opaque wchar iterator type. */
-struct wchar_iterator;
+/* An iterator that returns host wchar_t's from a target string. */
+class wchar_iterator
+{
+ public:

-/* Create a new character iterator which returns wchar_t's. INPUT is
- the input buffer. BYTES is the number of bytes in the input
- buffer. CHARSET is the name of the character set in which INPUT is
- encoded. WIDTH is the number of bytes in a base character of
- CHARSET.
+ /* Create a new character iterator which returns wchar_t's. INPUT is
+ the input buffer. BYTES is the number of bytes in the input
+ buffer. CHARSET is the name of the character set in which INPUT is
+ encoded. WIDTH is the number of bytes in a base character of
+ CHARSET.

- This function either returns a new character set iterator, or calls
- error. The result can be freed using a cleanup; see
- make_cleanup_wchar_iterator. */
-struct wchar_iterator *make_wchar_iterator (const gdb_byte *input,
- size_t bytes,
- const char *charset,
- size_t width);
-
-/* Return a new cleanup suitable for destroying the wchar iterator
- ITER. */
-struct cleanup *make_cleanup_wchar_iterator (struct wchar_iterator *iter);
-
-/* Perform a single iteration of a wchar_t iterator.
+ This function either returns a new character set iterator, or calls
+ error. The result can be freed using a cleanup; see
+ make_cleanup_wchar_iterator. */
+ wchar_iterator (const gdb_byte *input, size_t bytes, const char *charset,
+ size_t width);
+
+ ~wchar_iterator ();
+
+ /* Perform a single iteration of a wchar_t iterator.

- Returns the number of characters converted. A negative result
- means that EOF has been reached. A positive result indicates the
- number of valid wchar_ts in the result; *OUT_CHARS is updated to
- point to the first valid character.
+ Returns the number of characters converted. A negative result
+ means that EOF has been reached. A positive result indicates the
+ number of valid wchar_ts in the result; *OUT_CHARS is updated to
+ point to the first valid character.

- In all cases aside from EOF, *PTR is set to point to the first
- converted target byte. *LEN is set to the number of bytes
- converted.
+ In all cases aside from EOF, *PTR is set to point to the first
+ converted target byte. *LEN is set to the number of bytes
+ converted.

- A zero result means one of several unusual results. *OUT_RESULT is
- set to indicate the type of un-ordinary return.
+ A zero result means one of several unusual results. *OUT_RESULT is
+ set to indicate the type of un-ordinary return.

- wchar_iterate_invalid means that an invalid input character was
- seen. The iterator is advanced by WIDTH (the argument to
- make_wchar_iterator) bytes.
+ wchar_iterate_invalid means that an invalid input character was
+ seen. The iterator is advanced by WIDTH (the argument to
+ the wchar_iterator constructor) bytes.

- wchar_iterate_incomplete means that an incomplete character was
- seen at the end of the input sequence.
+ wchar_iterate_incomplete means that an incomplete character was
+ seen at the end of the input sequence.

- wchar_iterate_eof means that all bytes were successfully
- converted. The other output arguments are not set. */
-int wchar_iterate (struct wchar_iterator *iter,
- enum wchar_iterate_result *out_result,
- gdb_wchar_t **out_chars,
- const gdb_byte **ptr, size_t *len);
+ wchar_iterate_eof means that all bytes were successfully
+ converted. The other output arguments are not set. */
+ int iterate (enum wchar_iterate_result *out_result, gdb_wchar_t **out_chars,
+ const gdb_byte **ptr, size_t *len);
+
+ private:
+
+ /* The underlying iconv descriptor. */
+ iconv_t desc;
+
+ /* The input string. This is updated as convert characters. */
+ const gdb_byte *input;
+ /* The number of bytes remaining in the input. */
+ size_t bytes;
+
+ /* The width of an input character. */
+ size_t width;
+
+ /* The output buffer. */
+ std::vector<gdb_wchar_t> out;
+};

\f

diff --git a/gdb/valprint.c b/gdb/valprint.c
index 93607e5..ca30a7f 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -2404,19 +2404,16 @@ generic_emit_char (int c, struct type *type, struct ui_file *stream,
struct obstack wchar_buf, output;
struct cleanup *cleanups;
gdb_byte *buf;
- struct wchar_iterator *iter;
int need_escape = 0;

buf = (gdb_byte *) alloca (TYPE_LENGTH (type));
pack_long (buf, type, c);

- iter = make_wchar_iterator (buf, TYPE_LENGTH (type),
- encoding, TYPE_LENGTH (type));
- cleanups = make_cleanup_wchar_iterator (iter);
+ wchar_iterator iter (buf, TYPE_LENGTH (type), encoding, TYPE_LENGTH (type));

/* This holds the printable form of the wchar_t data. */
obstack_init (&wchar_buf);
- make_cleanup_obstack_free (&wchar_buf);
+ cleanups = make_cleanup_obstack_free (&wchar_buf);

while (1)
{
@@ -2427,7 +2424,7 @@ generic_emit_char (int c, struct type *type, struct ui_file *stream,
int print_escape = 1;
enum wchar_iterate_result result;

- num_chars = wchar_iterate (iter, &result, &chars, &buf, &buflen);
+ num_chars = iter.iterate (&result, &chars, &buf, &buflen);
if (num_chars < 0)
break;
if (num_chars > 0)
@@ -2481,7 +2478,7 @@ generic_emit_char (int c, struct type *type, struct ui_file *stream,
storing the result in VEC. */

static int
-count_next_character (struct wchar_iterator *iter,
+count_next_character (wchar_iterator *iter,
VEC (converted_character_d) **vec)
{
struct converted_character *current;
@@ -2492,7 +2489,7 @@ count_next_character (struct wchar_iterator *iter,
gdb_wchar_t *chars;

tmp.num_chars
- = wchar_iterate (iter, &tmp.result, &chars, &tmp.buf, &tmp.buflen);
+ = iter->iterate (&tmp.result, &chars, &tmp.buf, &tmp.buflen);
if (tmp.num_chars > 0)
{
gdb_assert (tmp.num_chars < MAX_WCHARS);
@@ -2521,8 +2518,7 @@ count_next_character (struct wchar_iterator *iter,
while (1)
{
/* Get the next character. */
- d.num_chars
- = wchar_iterate (iter, &d.result, &chars, &d.buf, &d.buflen);
+ d.num_chars = iter->iterate (&d.result, &chars, &d.buf, &d.buflen);

/* If a character was successfully converted, save the character
into the converted character. */
@@ -2736,7 +2732,6 @@ generic_printstr (struct ui_file *stream, struct type *type,
int width = TYPE_LENGTH (type);
struct obstack wchar_buf, output;
struct cleanup *cleanup;
- struct wchar_iterator *iter;
int finished = 0;
struct converted_character *last;
VEC (converted_character_d) *converted_chars;
@@ -2771,10 +2766,10 @@ generic_printstr (struct ui_file *stream, struct type *type,
}

/* Arrange to iterate over the characters, in wchar_t form. */
- iter = make_wchar_iterator (string, length * width, encoding, width);
- cleanup = make_cleanup_wchar_iterator (iter);
+ wchar_iterator iter (string, length * width, encoding, width);
converted_chars = NULL;
- make_cleanup (VEC_cleanup (converted_character_d), &converted_chars);
+ cleanup = make_cleanup (VEC_cleanup (converted_character_d),
+ &converted_chars);

/* Convert characters until the string is over or the maximum
number of printed characters has been reached. */
@@ -2786,7 +2781,7 @@ generic_printstr (struct ui_file *stream, struct type *type,
QUIT;

/* Grab the next character and repeat count. */
- r = count_next_character (iter, &converted_chars);
+ r = count_next_character (&iter, &converted_chars);

/* If less than zero, the end of the input string was reached. */
if (r < 0)
--
2.7.4