diff options
author | Pádraig Brady <P@draigBrady.com> | 2012-09-04 13:12:23 +0100 |
---|---|---|
committer | Pádraig Brady <P@draigBrady.com> | 2012-09-11 03:23:42 +0100 |
commit | 6cf9c59b1635906f3595fc43dcd36dc4433fd7aa (patch) | |
tree | b2a419c97f592646046443bae73191edd5ce3c86 | |
parent | 4fdd1cc597209b9e85ed66fdb594abca6f148155 (diff) | |
download | coreutils-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.c | 63 | ||||
-rw-r--r-- | gl/lib/mbsalign.h | 31 | ||||
-rw-r--r-- | gl/tests/test-mbsalign.c | 38 |
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; |