Turn wchar iterator into a class

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-10-12  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.
This commit is contained in:
Tom Tromey
2016-09-22 21:16:53 -06:00
parent 816d7b5304
commit cda6c55bd3
4 changed files with 114 additions and 130 deletions

View File

@@ -1,3 +1,21 @@
2016-10-12 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-10-12 Tom Tromey <tom@tromey.com> 2016-10-12 Tom Tromey <tom@tromey.com>
* selftest.c: Include <vector>, not "vec.h". * selftest.c: Include <vector>, not "vec.h".

View File

@@ -589,68 +589,27 @@ convert_between_encodings (const char *from, const char *to,
/* 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. */ /* Create a new iterator. */
struct wchar_iterator * wchar_iterator::wchar_iterator (const gdb_byte *input, size_t bytes,
make_wchar_iterator (const gdb_byte *input, size_t bytes,
const char *charset, size_t width) const char *charset, size_t width)
: m_input (input),
m_bytes (bytes),
m_width (width),
m_out (1)
{ {
struct wchar_iterator *result; m_desc = iconv_open (INTERMEDIATE_ENCODING, charset);
iconv_t desc; if (m_desc == (iconv_t) -1)
desc = iconv_open (INTERMEDIATE_ENCODING, charset);
if (desc == (iconv_t) -1)
perror_with_name (_("Converting character sets")); 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 wchar_iterator::~wchar_iterator ()
do_cleanup_iterator (void *p)
{ {
struct wchar_iterator *iter = (struct wchar_iterator *) p; if (m_desc != (iconv_t) -1)
iconv_close (m_desc);
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);
} }
int int
wchar_iterate (struct wchar_iterator *iter, wchar_iterator::iterate (enum wchar_iterate_result *out_result,
enum wchar_iterate_result *out_result,
gdb_wchar_t **out_chars, gdb_wchar_t **out_chars,
const gdb_byte **ptr, const gdb_byte **ptr,
size_t *len) size_t *len)
@@ -663,17 +622,17 @@ wchar_iterate (struct wchar_iterator *iter,
invalid input sequence -- but we want to reliably report this to invalid input sequence -- but we want to reliably report this to
our caller so it can emit an escape sequence. */ our caller so it can emit an escape sequence. */
out_request = 1; out_request = 1;
while (iter->bytes > 0) while (m_bytes > 0)
{ {
ICONV_CONST char *inptr = (ICONV_CONST char *) iter->input; ICONV_CONST char *inptr = (ICONV_CONST char *) m_input;
char *outptr = (char *) &iter->out[0]; char *outptr = (char *) m_out.data ();
const gdb_byte *orig_inptr = iter->input; const gdb_byte *orig_inptr = m_input;
size_t orig_in = iter->bytes; size_t orig_in = m_bytes;
size_t out_avail = out_request * sizeof (gdb_wchar_t); size_t out_avail = out_request * sizeof (gdb_wchar_t);
size_t num; size_t num;
size_t r = iconv (iter->desc, &inptr, &iter->bytes, &outptr, &out_avail); size_t r = iconv (m_desc, &inptr, &m_bytes, &outptr, &out_avail);
iter->input = (gdb_byte *) inptr; m_input = (gdb_byte *) inptr;
if (r == (size_t) -1) if (r == (size_t) -1)
{ {
@@ -688,10 +647,10 @@ wchar_iterate (struct wchar_iterator *iter,
/* Otherwise skip the first invalid character, and let /* Otherwise skip the first invalid character, and let
the caller know about it. */ the caller know about it. */
*out_result = wchar_iterate_invalid; *out_result = wchar_iterate_invalid;
*ptr = iter->input; *ptr = m_input;
*len = iter->width; *len = m_width;
iter->input += iter->width; m_input += m_width;
iter->bytes -= iter->width; m_bytes -= m_width;
return 0; return 0;
case E2BIG: case E2BIG:
@@ -702,20 +661,17 @@ wchar_iterate (struct wchar_iterator *iter,
break; break;
++out_request; ++out_request;
if (out_request > iter->out_size) if (out_request > m_out.size ())
{ m_out.reserve (out_request);
iter->out_size = out_request;
iter->out = XRESIZEVEC (gdb_wchar_t, iter->out, out_request);
}
continue; continue;
case EINVAL: case EINVAL:
/* Incomplete input sequence. Let the caller know, and /* Incomplete input sequence. Let the caller know, and
arrange for future calls to see EOF. */ arrange for future calls to see EOF. */
*out_result = wchar_iterate_incomplete; *out_result = wchar_iterate_incomplete;
*ptr = iter->input; *ptr = m_input;
*len = iter->bytes; *len = m_bytes;
iter->bytes = 0; m_bytes = 0;
return 0; return 0;
default: default:
@@ -727,9 +683,9 @@ wchar_iterate (struct wchar_iterator *iter,
/* We converted something. */ /* We converted something. */
num = out_request - out_avail / sizeof (gdb_wchar_t); num = out_request - out_avail / sizeof (gdb_wchar_t);
*out_result = wchar_iterate_ok; *out_result = wchar_iterate_ok;
*out_chars = iter->out; *out_chars = m_out.data ();
*ptr = orig_inptr; *ptr = orig_inptr;
*len = orig_in - iter->bytes; *len = orig_in - m_bytes;
return num; return num;
} }

View File

@@ -19,6 +19,8 @@
#ifndef CHARSET_H #ifndef CHARSET_H
#define CHARSET_H #define CHARSET_H
#include <vector>
/* If the target program uses a different character set than the host, /* If the target program uses a different character set than the host,
GDB has some support for translating between the two; GDB converts GDB has some support for translating between the two; GDB converts
characters and strings to the host character set before displaying characters and strings to the host character set before displaying
@@ -81,8 +83,10 @@ enum wchar_iterate_result
wchar_iterate_eof wchar_iterate_eof
}; };
/* Declaration of the opaque wchar iterator type. */ /* An iterator that returns host wchar_t's from a target string. */
struct wchar_iterator; class wchar_iterator
{
public:
/* Create a new character iterator which returns wchar_t's. INPUT is /* Create a new character iterator which returns wchar_t's. INPUT is
the input buffer. BYTES is the number of bytes in the input the input buffer. BYTES is the number of bytes in the input
@@ -93,14 +97,10 @@ struct wchar_iterator;
This function either returns a new character set iterator, or calls This function either returns a new character set iterator, or calls
error. The result can be freed using a cleanup; see error. The result can be freed using a cleanup; see
make_cleanup_wchar_iterator. */ make_cleanup_wchar_iterator. */
struct wchar_iterator *make_wchar_iterator (const gdb_byte *input, wchar_iterator (const gdb_byte *input, size_t bytes, const char *charset,
size_t bytes,
const char *charset,
size_t width); size_t width);
/* Return a new cleanup suitable for destroying the wchar iterator ~wchar_iterator ();
ITER. */
struct cleanup *make_cleanup_wchar_iterator (struct wchar_iterator *iter);
/* Perform a single iteration of a wchar_t iterator. /* Perform a single iteration of a wchar_t iterator.
@@ -118,18 +118,33 @@ struct cleanup *make_cleanup_wchar_iterator (struct wchar_iterator *iter);
wchar_iterate_invalid means that an invalid input character was wchar_iterate_invalid means that an invalid input character was
seen. The iterator is advanced by WIDTH (the argument to seen. The iterator is advanced by WIDTH (the argument to
make_wchar_iterator) bytes. the wchar_iterator constructor) bytes.
wchar_iterate_incomplete means that an incomplete character was wchar_iterate_incomplete means that an incomplete character was
seen at the end of the input sequence. seen at the end of the input sequence.
wchar_iterate_eof means that all bytes were successfully wchar_iterate_eof means that all bytes were successfully
converted. The other output arguments are not set. */ converted. The other output arguments are not set. */
int wchar_iterate (struct wchar_iterator *iter, int iterate (enum wchar_iterate_result *out_result, gdb_wchar_t **out_chars,
enum wchar_iterate_result *out_result,
gdb_wchar_t **out_chars,
const gdb_byte **ptr, size_t *len); const gdb_byte **ptr, size_t *len);
private:
/* The underlying iconv descriptor. */
iconv_t m_desc;
/* The input string. This is updated as we convert characters. */
const gdb_byte *m_input;
/* The number of bytes remaining in the input. */
size_t m_bytes;
/* The width of an input character. */
size_t m_width;
/* The output buffer. */
std::vector<gdb_wchar_t> m_out;
};
/* GDB needs to know a few details of its execution character set. /* GDB needs to know a few details of its execution character set.

View File

@@ -2404,19 +2404,16 @@ generic_emit_char (int c, struct type *type, struct ui_file *stream,
struct obstack wchar_buf, output; struct obstack wchar_buf, output;
struct cleanup *cleanups; struct cleanup *cleanups;
gdb_byte *buf; gdb_byte *buf;
struct wchar_iterator *iter;
int need_escape = 0; int need_escape = 0;
buf = (gdb_byte *) alloca (TYPE_LENGTH (type)); buf = (gdb_byte *) alloca (TYPE_LENGTH (type));
pack_long (buf, type, c); pack_long (buf, type, c);
iter = make_wchar_iterator (buf, TYPE_LENGTH (type), wchar_iterator iter (buf, TYPE_LENGTH (type), encoding, TYPE_LENGTH (type));
encoding, TYPE_LENGTH (type));
cleanups = make_cleanup_wchar_iterator (iter);
/* This holds the printable form of the wchar_t data. */ /* This holds the printable form of the wchar_t data. */
obstack_init (&wchar_buf); obstack_init (&wchar_buf);
make_cleanup_obstack_free (&wchar_buf); cleanups = make_cleanup_obstack_free (&wchar_buf);
while (1) while (1)
{ {
@@ -2427,7 +2424,7 @@ generic_emit_char (int c, struct type *type, struct ui_file *stream,
int print_escape = 1; int print_escape = 1;
enum wchar_iterate_result result; 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) if (num_chars < 0)
break; break;
if (num_chars > 0) 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. */ storing the result in VEC. */
static int static int
count_next_character (struct wchar_iterator *iter, count_next_character (wchar_iterator *iter,
VEC (converted_character_d) **vec) VEC (converted_character_d) **vec)
{ {
struct converted_character *current; struct converted_character *current;
@@ -2492,7 +2489,7 @@ count_next_character (struct wchar_iterator *iter,
gdb_wchar_t *chars; gdb_wchar_t *chars;
tmp.num_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) if (tmp.num_chars > 0)
{ {
gdb_assert (tmp.num_chars < MAX_WCHARS); gdb_assert (tmp.num_chars < MAX_WCHARS);
@@ -2521,8 +2518,7 @@ count_next_character (struct wchar_iterator *iter,
while (1) while (1)
{ {
/* Get the next character. */ /* Get the next character. */
d.num_chars d.num_chars = iter->iterate (&d.result, &chars, &d.buf, &d.buflen);
= wchar_iterate (iter, &d.result, &chars, &d.buf, &d.buflen);
/* If a character was successfully converted, save the character /* If a character was successfully converted, save the character
into the converted character. */ into the converted character. */
@@ -2736,7 +2732,6 @@ generic_printstr (struct ui_file *stream, struct type *type,
int width = TYPE_LENGTH (type); int width = TYPE_LENGTH (type);
struct obstack wchar_buf, output; struct obstack wchar_buf, output;
struct cleanup *cleanup; struct cleanup *cleanup;
struct wchar_iterator *iter;
int finished = 0; int finished = 0;
struct converted_character *last; struct converted_character *last;
VEC (converted_character_d) *converted_chars; 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. */ /* Arrange to iterate over the characters, in wchar_t form. */
iter = make_wchar_iterator (string, length * width, encoding, width); wchar_iterator iter (string, length * width, encoding, width);
cleanup = make_cleanup_wchar_iterator (iter);
converted_chars = NULL; 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 /* Convert characters until the string is over or the maximum
number of printed characters has been reached. */ number of printed characters has been reached. */
@@ -2786,7 +2781,7 @@ generic_printstr (struct ui_file *stream, struct type *type,
QUIT; QUIT;
/* Grab the next character and repeat count. */ /* 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 less than zero, the end of the input string was reached. */
if (r < 0) if (r < 0)