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,71 +589,30 @@ 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)
{ {
size_t out_request; 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 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,54 +83,67 @@ 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
buffer. CHARSET is the name of the character set in which INPUT is 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 encoded. WIDTH is the number of bytes in a base character of
CHARSET. CHARSET.
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, size_t width);
const char *charset,
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.
Returns the number of characters converted. A negative result Returns the number of characters converted. A negative result
means that EOF has been reached. A positive result indicates the means that EOF has been reached. A positive result indicates the
number of valid wchar_ts in the result; *OUT_CHARS is updated to number of valid wchar_ts in the result; *OUT_CHARS is updated to
point to the first valid character. point to the first valid character.
In all cases aside from EOF, *PTR is set to point to the first 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 target byte. *LEN is set to the number of bytes
converted. converted.
A zero result means one of several unusual results. *OUT_RESULT is A zero result means one of several unusual results. *OUT_RESULT is
set to indicate the type of un-ordinary return. set to indicate the type of un-ordinary return.
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, const gdb_byte **ptr, size_t *len);
gdb_wchar_t **out_chars,
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;
};

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)