mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-02-17 12:52:16 +02:00
maint: add more control flags to mbsalign
* gl/lib/mbsalign.h: Add MBA_UNIBYTE_ONLY (to allow faster processing). Also add MBA_NO_LEFT_PAD, MBA_NO_RIGHT_PAD to give greater control of padding, useful with the first or last fields on a line. * gl/lib/mbsalign.c (mbsalign): Implement the new flags. * gl/tests/test-mbsalign.c (main): Test combinations of the new flags.
This commit is contained in:
@@ -126,7 +126,7 @@ mbsalign (const char *src, char *dest, size_t dest_size,
|
||||
/* In multi-byte locales convert to wide characters
|
||||
to allow easy truncation. Also determine number
|
||||
of screen columns used. */
|
||||
if (MB_CUR_MAX > 1)
|
||||
if (!(flags & MBA_UNIBYTE_ONLY) && MB_CUR_MAX > 1)
|
||||
{
|
||||
size_t src_chars = mbstowcs (NULL, src, 0);
|
||||
if (src_chars == SIZE_MAX)
|
||||
@@ -191,37 +191,46 @@ mbsalign_unibyte:
|
||||
/* indicate to caller how many cells needed (not including padding). */
|
||||
*width = n_cols;
|
||||
|
||||
/* indicate to caller how many bytes needed (not including NUL). */
|
||||
ret = n_used_bytes + (n_spaces * 1);
|
||||
{
|
||||
size_t start_spaces, end_spaces;
|
||||
|
||||
/* Write as much NUL terminated output to DEST as possible. */
|
||||
if (dest_size != 0)
|
||||
{
|
||||
size_t start_spaces, end_spaces, space_left;
|
||||
char *dest_end = dest + dest_size - 1;
|
||||
switch (align)
|
||||
{
|
||||
case MBS_ALIGN_LEFT:
|
||||
start_spaces = 0;
|
||||
end_spaces = n_spaces;
|
||||
break;
|
||||
case MBS_ALIGN_RIGHT:
|
||||
start_spaces = n_spaces;
|
||||
end_spaces = 0;
|
||||
break;
|
||||
case MBS_ALIGN_CENTER:
|
||||
default:
|
||||
start_spaces = n_spaces / 2 + n_spaces % 2;
|
||||
end_spaces = n_spaces / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (align)
|
||||
if (flags & MBA_NO_LEFT_PAD)
|
||||
start_spaces = 0;
|
||||
if (flags & MBA_NO_RIGHT_PAD)
|
||||
end_spaces = 0;
|
||||
|
||||
/* Write as much NUL terminated output to DEST as possible. */
|
||||
if (dest_size != 0)
|
||||
{
|
||||
case MBS_ALIGN_LEFT:
|
||||
start_spaces = 0;
|
||||
end_spaces = n_spaces;
|
||||
break;
|
||||
case MBS_ALIGN_RIGHT:
|
||||
start_spaces = n_spaces;
|
||||
end_spaces = 0;
|
||||
break;
|
||||
case MBS_ALIGN_CENTER:
|
||||
default:
|
||||
start_spaces = n_spaces / 2 + n_spaces % 2;
|
||||
end_spaces = n_spaces / 2;
|
||||
break;
|
||||
size_t space_left;
|
||||
char *dest_end = dest + dest_size - 1;
|
||||
|
||||
dest = mbs_align_pad (dest, dest_end, start_spaces);
|
||||
space_left = dest_end - dest;
|
||||
dest = mempcpy (dest, str_to_print, MIN (n_used_bytes, space_left));
|
||||
mbs_align_pad (dest, dest_end, end_spaces);
|
||||
}
|
||||
|
||||
dest = mbs_align_pad (dest, dest_end, start_spaces);
|
||||
space_left = dest_end - dest;
|
||||
dest = mempcpy (dest, str_to_print, MIN (n_used_bytes, space_left));
|
||||
mbs_align_pad (dest, dest_end, end_spaces);
|
||||
}
|
||||
/* indicate to caller how many bytes needed (not including NUL). */
|
||||
ret = n_used_bytes + ((start_spaces + end_spaces) * 1);
|
||||
}
|
||||
|
||||
mbsalign_cleanup:
|
||||
|
||||
|
||||
@@ -21,20 +21,33 @@ typedef enum { MBS_ALIGN_LEFT, MBS_ALIGN_RIGHT, MBS_ALIGN_CENTER } mbs_align_t;
|
||||
enum {
|
||||
/* Use unibyte mode for invalid multibyte strings
|
||||
or when heap memory is exhausted. */
|
||||
MBA_UNIBYTE_FALLBACK = 0x0001
|
||||
MBA_UNIBYTE_FALLBACK = 0x0001,
|
||||
|
||||
/* As an optimization, don't do multibyte processing
|
||||
when we know no multibyte characters are present. */
|
||||
MBA_UNIBYTE_ONLY = 0x0002,
|
||||
|
||||
/* Don't add leading padding. */
|
||||
MBA_NO_LEFT_PAD = 0x0004,
|
||||
|
||||
/* Don't add trailing padding. */
|
||||
MBA_NO_RIGHT_PAD = 0x0008
|
||||
|
||||
#if 0 /* Other possible options. */
|
||||
/* Skip invalid multibyte chars rather than failing */
|
||||
MBA_IGNORE_INVALID = 0x0002,
|
||||
/* Skip invalid multibyte chars rather than failing. */
|
||||
MBA_IGNORE_INVALID
|
||||
|
||||
/* Align multibyte strings using "figure space" (\u2007) */
|
||||
MBA_USE_FIGURE_SPACE = 0x0004,
|
||||
/* Align multibyte strings using "figure space" (\u2007). */
|
||||
MBA_USE_FIGURE_SPACE
|
||||
|
||||
/* Don't add any padding */
|
||||
MBA_TRUNCATE_ONLY = 0x0008,
|
||||
/* Don't truncate. */
|
||||
MBA_NO_TRUNCATE
|
||||
|
||||
/* Don't truncate */
|
||||
MBA_PAD_ONLY = 0x0010,
|
||||
/* Ensure no leading whitepsace. */
|
||||
MBA_LSTRIP
|
||||
|
||||
/* Ensure no trailing whitepsace. */
|
||||
MBA_RSTRIP
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -38,6 +38,35 @@ main (void)
|
||||
width = 4;
|
||||
n = mbsalign ("es", dest, sizeof dest, &width, MBS_ALIGN_CENTER, 0);
|
||||
ASSERT (*dest == ' ' && *(dest + n - 1) == ' ');
|
||||
ASSERT (n == 4);
|
||||
|
||||
/* Test center alignment, with no trailing padding. */
|
||||
width = 4;
|
||||
n = mbsalign ("es", dest, sizeof dest, &width, MBS_ALIGN_CENTER,
|
||||
MBA_NO_RIGHT_PAD);
|
||||
ASSERT (n == 3);
|
||||
ASSERT (*dest == ' ' && *(dest + n - 1) == 's');
|
||||
|
||||
/* Test left alignment, with no trailing padding. (truncate only). */
|
||||
width = 4;
|
||||
n = mbsalign ("es", dest, sizeof dest, &width, MBS_ALIGN_LEFT,
|
||||
MBA_NO_RIGHT_PAD);
|
||||
ASSERT (n == 2);
|
||||
ASSERT (*dest == 'e' && *(dest + n - 1) == 's');
|
||||
|
||||
/* Test center alignment, with no padding. (truncate only). */
|
||||
width = 4;
|
||||
n = mbsalign ("es", dest, sizeof dest, &width, MBS_ALIGN_CENTER,
|
||||
MBA_NO_LEFT_PAD | MBA_NO_RIGHT_PAD);
|
||||
ASSERT (n == 2);
|
||||
ASSERT (*dest == 'e' && *(dest + n - 1) == 's');
|
||||
|
||||
/* Test center alignment, with no left padding. (may be useful for RTL?) */
|
||||
width = 4;
|
||||
n = mbsalign ("es", dest, sizeof dest, &width, MBS_ALIGN_CENTER,
|
||||
MBA_NO_LEFT_PAD);
|
||||
ASSERT (n == 3);
|
||||
ASSERT (*dest == 'e' && *(dest + n - 1) == ' ');
|
||||
|
||||
if (setlocale (LC_ALL, "en_US.UTF8"))
|
||||
{
|
||||
@@ -55,16 +84,19 @@ main (void)
|
||||
/* Test multibyte center alignment. */
|
||||
width = 4;
|
||||
n = mbsalign ("és", dest, sizeof dest, &width, MBS_ALIGN_CENTER, 0);
|
||||
ASSERT (n == 5);
|
||||
ASSERT (*dest == ' ' && *(dest + n - 1) == ' ');
|
||||
|
||||
/* Test multibyte left alignment. */
|
||||
width = 4;
|
||||
n = mbsalign ("és", dest, sizeof dest, &width, MBS_ALIGN_LEFT, 0);
|
||||
ASSERT (n == 5);
|
||||
ASSERT (*(dest + n - 1) == ' ' && *(dest + n - 2) == ' ');
|
||||
|
||||
/* Test multibyte right alignment. */
|
||||
width = 4;
|
||||
n = mbsalign ("és", dest, sizeof dest, &width, MBS_ALIGN_RIGHT, 0);
|
||||
ASSERT (n == 5);
|
||||
ASSERT (*(dest) == ' ' && *(dest + 1) == ' ');
|
||||
|
||||
/* multibyte multicell truncation. */
|
||||
@@ -94,6 +126,12 @@ main (void)
|
||||
n = mbsalign ("t\tés" /* 6 including NUL */ , dest, sizeof dest,
|
||||
&width, MBS_ALIGN_LEFT, 0);
|
||||
ASSERT (n == 7);
|
||||
|
||||
/* Test forced unibyte truncation. */
|
||||
width = 4;
|
||||
n = mbsalign ("t\tés", dest, sizeof dest, &width, MBS_ALIGN_LEFT,
|
||||
MBA_UNIBYTE_ONLY);
|
||||
ASSERT (n == 4);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user