]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
maint: add more control flags to mbsalign
authorPádraig Brady <P@draigBrady.com>
Tue, 4 Sep 2012 12:12:23 +0000 (13:12 +0100)
committerPádraig Brady <P@draigBrady.com>
Tue, 11 Sep 2012 02:23:42 +0000 (03:23 +0100)
* 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.

gl/lib/mbsalign.c
gl/lib/mbsalign.h
gl/tests/test-mbsalign.c

index e45456bf90371114879404abef00f9908fc59fd2..3c3170a8d3f9bfa53cedfd40e978c4c00ca20c99 100644 (file)
@@ -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:
 
index e9340f926d57d24a50b0562f0eb9768ee01184e7..25d529e488265c75a426fc560877d41cd7901285 100644 (file)
@@ -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
 };
 
index 86aa87739dcc479547c36c81e3a89292f5febee0..11e9dee0e0bb3c7969361ba970219ac08723dc29 100644 (file)
@@ -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;