glibc/support/support_quote_blob_main.c
Joseph Myers de82cb0da4 Add TEST_COMPARE_STRING_WIDE to support/check.h
I'd like to be able to test narrow and wide string interfaces, with
the narrow string tests using TEST_COMPARE_STRING and the wide string
tests using something analogous (possibly generated using macros from
a common test template for both the narrow and wide string tests where
appropriate).

Add such a TEST_COMPARE_STRING_WIDE, along with functions
support_quote_blob_wide and support_test_compare_string_wide that it
builds on.  Those functions are built using macros from common
templates shared by the narrow and wide string implementations, though
I didn't do that for the tests of test functions.  In
support_quote_blob_wide, I chose to use the \x{} delimited escape
sequence syntax proposed for C2X in N2785, rather than e.g. trying to
generate the end of a string and the start of a new string when
ambiguity would result from undelimited \x (when the next character
after such an escape sequence is valid hex) or forcing an escape
sequence to be used for the next character in the case of such
ambiguity.

Tested for x86_64.
2021-10-12 13:48:39 +00:00

89 lines
2.4 KiB
C

/* Quote a blob so that it can be used in C literals.
Copyright (C) 2018-2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <support/support.h>
#include <support/xmemstream.h>
char *
SUPPORT_QUOTE_BLOB (const void *blob, size_t length)
{
struct xmemstream out;
xopen_memstream (&out);
const CHAR *p = blob;
for (size_t i = 0; i < length; ++i)
{
CHAR ch = p[i];
/* Use C backslash escapes for those control characters for
which they are defined. */
switch (ch)
{
case L_('\a'):
putc_unlocked ('\\', out.out);
putc_unlocked ('a', out.out);
break;
case L_('\b'):
putc_unlocked ('\\', out.out);
putc_unlocked ('b', out.out);
break;
case L_('\f'):
putc_unlocked ('\\', out.out);
putc_unlocked ('f', out.out);
break;
case L_('\n'):
putc_unlocked ('\\', out.out);
putc_unlocked ('n', out.out);
break;
case L_('\r'):
putc_unlocked ('\\', out.out);
putc_unlocked ('r', out.out);
break;
case L_('\t'):
putc_unlocked ('\\', out.out);
putc_unlocked ('t', out.out);
break;
case L_('\v'):
putc_unlocked ('\\', out.out);
putc_unlocked ('v', out.out);
break;
case L_('\\'):
case L_('\''):
case L_('\"'):
putc_unlocked ('\\', out.out);
putc_unlocked (ch, out.out);
break;
default:
if (ch < L_(' ') || ch > L_('~'))
/* For narrow characters, use octal sequences because they
are fixed width, unlike hexadecimal sequences. For
wide characters, use N2785 delimited escape
sequences. */
if (WIDE)
fprintf (out.out, "\\x{%x}", (unsigned int) ch);
else
fprintf (out.out, "\\%03o", (unsigned int) ch);
else
putc_unlocked (ch, out.out);
}
}
xfclose_memstream (&out);
return out.buffer;
}