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>
* 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. */
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)
: m_input (input),
m_bytes (bytes),
m_width (width),
m_out (1)
{
struct wchar_iterator *result;
iconv_t desc;
desc = iconv_open (INTERMEDIATE_ENCODING, charset);
if (desc == (iconv_t) -1)
m_desc = iconv_open (INTERMEDIATE_ENCODING, charset);
if (m_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 (m_desc != (iconv_t) -1)
iconv_close (m_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 (m_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 *) m_input;
char *outptr = (char *) m_out.data ();
const gdb_byte *orig_inptr = m_input;
size_t orig_in = m_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 (m_desc, &inptr, &m_bytes, &outptr, &out_avail);
iter->input = (gdb_byte *) inptr;
m_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 = m_input;
*len = m_width;
m_input += m_width;
m_bytes -= m_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 > m_out.size ())
m_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 = m_input;
*len = m_bytes;
m_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 = m_out.data ();
*ptr = orig_inptr;
*len = orig_in - iter->bytes;
*len = orig_in - m_bytes;
return num;
}

View File

@ -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);
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);
/* Return a new cleanup suitable for destroying the wchar iterator
ITER. */
struct cleanup *make_cleanup_wchar_iterator (struct wchar_iterator *iter);
~wchar_iterator ();
/* 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
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 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 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)