summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2012-09-04 13:12:23 +0100
committerPádraig Brady <P@draigBrady.com>2012-09-11 03:23:42 +0100
commit6cf9c59b1635906f3595fc43dcd36dc4433fd7aa (patch)
treeb2a419c97f592646046443bae73191edd5ce3c86
parent4fdd1cc597209b9e85ed66fdb594abca6f148155 (diff)
downloadcoreutils-6cf9c59b1635906f3595fc43dcd36dc4433fd7aa.tar.xz
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.
-rw-r--r--gl/lib/mbsalign.c63
-rw-r--r--gl/lib/mbsalign.h31
-rw-r--r--gl/tests/test-mbsalign.c38
3 files changed, 96 insertions, 36 deletions
diff --git a/gl/lib/mbsalign.c b/gl/lib/mbsalign.c
index e45456bf9..3c3170a8d 100644
--- a/gl/lib/mbsalign.c
+++ b/gl/lib/mbsalign.c
@@ -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;
+ }
+
+ if (flags & MBA_NO_LEFT_PAD)
+ start_spaces = 0;
+ if (flags & MBA_NO_RIGHT_PAD)
+ end_spaces = 0;
- switch (align)
+ /* 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:
diff --git a/gl/lib/mbsalign.h b/gl/lib/mbsalign.h
index e9340f926..25d529e48 100644
--- a/gl/lib/mbsalign.h
+++ b/gl/lib/mbsalign.h
@@ -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
- /* Align multibyte strings using "figure space" (\u2007) */
- MBA_USE_FIGURE_SPACE = 0x0004,
+ /* Don't truncate. */
+ MBA_NO_TRUNCATE
- /* Don't add any padding */
- MBA_TRUNCATE_ONLY = 0x0008,
+ /* Ensure no leading whitepsace. */
+ MBA_LSTRIP
- /* Don't truncate */
- MBA_PAD_ONLY = 0x0010,
+ /* Ensure no trailing whitepsace. */
+ MBA_RSTRIP
#endif
};
diff --git a/gl/tests/test-mbsalign.c b/gl/tests/test-mbsalign.c
index 86aa87739..11e9dee0e 100644
--- a/gl/tests/test-mbsalign.c
+++ b/gl/tests/test-mbsalign.c
@@ -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;