namespace selftests {
namespace format_pieces {
+/* Like format_piece, but with the expected string hardcoded instead of an
+ index. */
+
+struct expected_format_piece
+{
+ std::string_view str;
+ enum argclass argclass;
+ int n_int_args;
+};
+
/* Verify that parsing STR gives pieces equal to EXPECTED_PIECES. */
static void
-check (const char *str, const std::vector<format_piece> &expected_pieces,
+check (const char *str,
+ const std::vector<expected_format_piece> &expected_pieces,
bool gdb_format = false)
{
::format_pieces pieces (&str, gdb_format);
SELF_CHECK ((pieces.end () - pieces.begin ()) == expected_pieces.size ());
- SELF_CHECK (std::equal (pieces.begin (), pieces.end (),
- expected_pieces.begin ()));
+
+ for (auto it = pieces.begin (); it != pieces.end (); ++it)
+ {
+ auto &expected = expected_pieces[it - pieces.begin ()];
+
+ SELF_CHECK (expected.str == pieces.piece_str (*it));
+ SELF_CHECK (expected.argclass == it->argclass);
+ SELF_CHECK (expected.n_int_args == it->n_int_args);
+ }
}
static void
{
check ("This is an escape sequence: \\e",
{
- format_piece ("This is an escape sequence: \e", literal_piece, 0),
+ {"This is an escape sequence: \e", literal_piece, 0},
});
}
see a trailing empty literal piece. */
check ("Hello\\t %d%llx%%d%d", /* ARI: %ll */
{
- format_piece ("Hello\t ", literal_piece, 0),
- format_piece ("%d", int_arg, 0),
- format_piece ("%" LL "x", long_long_arg, 0),
- format_piece ("%%d", literal_piece, 0),
- format_piece ("%d", int_arg, 0),
+ {"Hello\t ", literal_piece, 0},
+ {"%d", int_arg, 0},
+ {"%" LL "x", long_long_arg, 0},
+ {"%%d", literal_piece, 0},
+ {"%d", int_arg, 0},
});
}
{
check ("Hello\\t \"%p[%pF%ps%*.*d%p]\"",
{
- format_piece ("Hello\\t \"", literal_piece, 0),
- format_piece ("%p[", ptr_arg, 0),
- format_piece ("%pF", ptr_arg, 0),
- format_piece ("%ps", ptr_arg, 0),
- format_piece ("%*.*d", int_arg, 2),
- format_piece ("%p]", ptr_arg, 0),
- format_piece ("\"", literal_piece, 0),
+ {"Hello\\t \"", literal_piece, 0},
+ {"%p[", ptr_arg, 0},
+ {"%pF", ptr_arg, 0},
+ {"%ps", ptr_arg, 0},
+ {"%*.*d", int_arg, 2},
+ {"%p]", ptr_arg, 0},
+ {"\"", literal_piece, 0},
}, true);
}
{
check ("Hello\\t %hu%lu%llu%zu", /* ARI: %ll */
{
- format_piece ("Hello\t ", literal_piece, 0),
- format_piece ("%hu", int_arg, 0),
- format_piece ("%lu", long_arg, 0),
- format_piece ("%" LL "u", long_long_arg, 0),
- format_piece ("%zu", size_t_arg, 0)
+ {"Hello\t ", literal_piece, 0},
+ {"%hu", int_arg, 0},
+ {"%lu", long_arg, 0},
+ {"%" LL "u", long_long_arg, 0},
+ {"%zu", size_t_arg, 0},
});
check ("Hello\\t %hx%lx%llx%zx", /* ARI: %ll */
{
- format_piece ("Hello\t ", literal_piece, 0),
- format_piece ("%hx", int_arg, 0),
- format_piece ("%lx", long_arg, 0),
- format_piece ("%" LL "x", long_long_arg, 0),
- format_piece ("%zx", size_t_arg, 0)
+ {"Hello\t ", literal_piece, 0},
+ {"%hx", int_arg, 0},
+ {"%lx", long_arg, 0},
+ {"%" LL "x", long_long_arg, 0},
+ {"%zx", size_t_arg, 0},
});
check ("Hello\\t %ho%lo%llo%zo", /* ARI: %ll */
{
- format_piece ("Hello\t ", literal_piece, 0),
- format_piece ("%ho", int_arg, 0),
- format_piece ("%lo", long_arg, 0),
- format_piece ("%" LL "o", long_long_arg, 0),
- format_piece ("%zo", size_t_arg, 0)
+ {"Hello\t ", literal_piece, 0},
+ {"%ho", int_arg, 0},
+ {"%lo", long_arg, 0},
+ {"%" LL "o", long_long_arg, 0},
+ {"%zo", size_t_arg, 0},
});
check ("Hello\\t %hd%ld%lld%zd", /* ARI: %ll */
{
- format_piece ("Hello\t ", literal_piece, 0),
- format_piece ("%hd", int_arg, 0),
- format_piece ("%ld", long_arg, 0),
- format_piece ("%" LL "d", long_long_arg, 0),
- format_piece ("%zd", size_t_arg, 0)
+ {"Hello\t ", literal_piece, 0},
+ {"%hd", int_arg, 0},
+ {"%ld", long_arg, 0},
+ {"%" LL "d", long_long_arg, 0},
+ {"%zd", size_t_arg, 0},
});
}
{
check ("rc%I64d",
{
- format_piece ("rc", literal_piece, 0),
- format_piece ("%I64d", long_long_arg, 0),
+ {"rc", literal_piece, 0},
+ {"%I64d", long_long_arg, 0},
});
}
*arg = s;
}
- /* Need extra space for the '\0's. Doubling the size is sufficient. */
- char *current_substring = (char *) xmalloc (strlen (string) * 2 + 1000);
- m_storage.reset (current_substring);
-
/* Now scan the string for %-specs and see what kinds of args they want.
argclass classifies the %-specs so we can give printf-type functions
something of the right size. */
continue;
}
- const char *sub_start = current_substring;
+ std::string::size_type sub_start = m_storage.size ();
- strncpy (current_substring, prev_start, f - 1 - prev_start);
- current_substring += f - 1 - prev_start;
- *current_substring++ = '\0';
+ m_storage.append (prev_start, f - 1 - prev_start);
+ m_storage += '\0';
- if (*sub_start != '\0')
+ if (m_storage[sub_start] != '\0')
m_pieces.emplace_back (sub_start, literal_piece, 0);
const char *percent_loc = f - 1;
f++;
- sub_start = current_substring;
+ sub_start = m_storage.size ();
if (lcount > 1 && !seen_i64 && USE_PRINTF_I64)
{
Convert %lld to %I64d. */
int length_before_ll = f - percent_loc - 1 - lcount;
- strncpy (current_substring, percent_loc, length_before_ll);
- strcpy (current_substring + length_before_ll, "I64");
- current_substring[length_before_ll + 3] =
- percent_loc[length_before_ll + lcount];
- current_substring += length_before_ll + 4;
+ m_storage.append (percent_loc, length_before_ll);
+ m_storage += "I64";
+ m_storage += percent_loc[length_before_ll + lcount];
}
else if (this_argclass == wide_string_arg
|| this_argclass == wide_char_arg)
/* Convert %ls or %lc to %s. */
int length_before_ls = f - percent_loc - 2;
- strncpy (current_substring, percent_loc, length_before_ls);
- strcpy (current_substring + length_before_ls, "s");
- current_substring += length_before_ls + 2;
+ m_storage.append (percent_loc, length_before_ls);
+ m_storage += "s";
}
else
- {
- strncpy (current_substring, percent_loc, f - percent_loc);
- current_substring += f - percent_loc;
- }
-
- *current_substring++ = '\0';
+ m_storage.append (percent_loc, f - percent_loc);
+ m_storage += '\0';
prev_start = f;
m_pieces.emplace_back (sub_start, this_argclass, n_int_args);
if (f > prev_start)
{
- const char *sub_start = current_substring;
-
- strncpy (current_substring, prev_start, f - prev_start);
- current_substring += f - prev_start;
- *current_substring++ = '\0';
+ std::string::size_type sub_start = m_storage.size ();
+ m_storage.append (prev_start, f - prev_start);
+ /* No need for a final '\0', std::string already has one. */
m_pieces.emplace_back (sub_start, literal_piece, 0);
}