Tom Lane wrote:
> > The only question I have is whether those locale values are single-byte
> > strings in all locals, or could they be multi-byte or multi-character,
> > in which case I have to treat them as strings.
> 
> I think you have to assume they could be strings.

OK, the following applied patch enables multi-byte locale strings for
numericsep.  I also reorganized the code a little.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: src/bin/psql/print.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/print.c,v
retrieving revision 1.68
diff -c -c -r1.68 print.c
*** src/bin/psql/print.c        14 Jul 2005 15:54:21 -0000      1.68
--- src/bin/psql/print.c        14 Jul 2005 20:54:05 -0000
***************
*** 50,125 ****
  }
  
  static int
! num_numericseps(const char *my_str)
  {
!       int old_len, dec_len, int_len;
!       int     groupdigits = atoi(grouping);
  
        if (my_str[0] == '-')
                my_str++;
      
!       old_len = strlen(my_str);
!       dec_len = strchr(my_str, '.') ? strlen(strchr(my_str, '.')) : 0;
  
-       int_len = old_len - dec_len;
        if (int_len % groupdigits != 0)
!               return int_len / groupdigits;
        else
!               return int_len / groupdigits - 1;       /* no leading separator 
*/
  }
  
  static int
  len_with_numericsep(const char *my_str)
  {
!       return strlen(my_str) + num_numericseps(my_str);
  }
  
  static void 
  format_numericsep(char *my_str)
  {
!       int i, j, digits_before_sep, old_len, new_len, dec_len, int_len;
!       char *new_str;
!       char *dec_value;
        int     groupdigits = atoi(grouping);
      
        if (my_str[0] == '-')
                my_str++;
!     
!       old_len = strlen(my_str);
!       dec_len = strchr(my_str, '.') ? strlen(strchr(my_str, '.')) : 0;
!       int_len = old_len - dec_len;
!       digits_before_sep = int_len % groupdigits;
! 
!       new_len = int_len + int_len / groupdigits + dec_len;
!       if (digits_before_sep == 0)
!               new_len--;      /* no leading separator */
  
!       new_str = pg_local_malloc(new_len + 1);
  
        for (i=0, j=0; ; i++, j++)
        {
!               /* hit decimal point */
                if (my_str[i] == '.')
                {
!                       new_str[j] = *decimal_point;
!                       new_str[j+1] = '\0';
!                       dec_value = strchr(my_str, '.');
!                       strcat(new_str, ++dec_value);
                        break;
                }
  
!               /* end of string */
                if (my_str[i] == '\0')
                {
                        new_str[j] = '\0';
                        break;
                }
      
!               /* add separator? */
!               if (i != 0 &&
!                       (i - (digits_before_sep ? digits_before_sep : 
groupdigits))
!                               % groupdigits == 0)
!                       new_str[j++] = *thousands_sep;
  
                new_str[j] = my_str[i];
        }
--- 50,128 ----
  }
  
  static int
! integer_digits(const char *my_str)
  {
!       int frac_len;
  
        if (my_str[0] == '-')
                my_str++;
      
!       frac_len = strchr(my_str, '.') ? strlen(strchr(my_str, '.')) : 0;
! 
!       return strlen(my_str) - frac_len;
! }
! 
! static int
! len_numericseps(const char *my_str)
! {
!       int int_len = integer_digits(my_str), sep_len;
!       int     groupdigits = atoi(grouping);
  
        if (int_len % groupdigits != 0)
!               sep_len = int_len / groupdigits;
        else
!               sep_len = int_len / groupdigits - 1;    /* no leading separator 
*/
! 
!       return sep_len * strlen(thousands_sep) -
!                  strlen(".") + strlen(decimal_point);
  }
  
  static int
  len_with_numericsep(const char *my_str)
  {
!       return strlen(my_str) + len_numericseps(my_str);
  }
  
  static void 
  format_numericsep(char *my_str)
  {
!       int i, j, int_len = integer_digits(my_str), leading_digits;
        int     groupdigits = atoi(grouping);
+       char *new_str;
      
        if (my_str[0] == '-')
                my_str++;
!       
!       new_str = pg_local_malloc(len_numericseps(my_str) + 1);
  
!       leading_digits = (int_len % groupdigits != 0) ?
!                                        int_len % groupdigits : groupdigits;
  
        for (i=0, j=0; ; i++, j++)
        {
!               /* Hit decimal point? */
                if (my_str[i] == '.')
                {
!                       strcpy(&new_str[j], decimal_point);
!                       j += strlen(decimal_point);
!                       /* add fractional part */
!                       strcpy(&new_str[j], &my_str[i] + 1);
                        break;
                }
  
!               /* End of string? */
                if (my_str[i] == '\0')
                {
                        new_str[j] = '\0';
                        break;
                }
      
!               /* Add separator? */
!               if (i != 0 && (i - leading_digits) % groupdigits == 0)
!               {
!                       strcpy(&new_str[j], thousands_sep);
!                       j += strlen(thousands_sep);
!               }
  
                new_str[j] = my_str[i];
        }
***************
*** 396,402 ****
                int numericseps;
  
                if (opt_align[i % col_count] == 'r' && opt_numericsep)
!                   numericseps = num_numericseps(*ptr);
                else 
                    numericseps = 0;
                
--- 399,405 ----
                int numericseps;
  
                if (opt_align[i % col_count] == 'r' && opt_numericsep)
!                   numericseps = len_numericseps(*ptr);
                else 
                    numericseps = 0;
                
***************
*** 613,619 ****
                int numericseps;
  
                if (opt_align[i % col_count] == 'r' && opt_numericsep)
!                   numericseps = num_numericseps(*ptr);
                else 
                    numericseps = 0;
  
--- 616,622 ----
                int numericseps;
  
                if (opt_align[i % col_count] == 'r' && opt_numericsep)
!                   numericseps = len_numericseps(*ptr);
                else 
                    numericseps = 0;
  
***************
*** 1711,1717 ****
  
        extlconv = localeconv();
  
-       /* These are treated as single-byte strings in the code */
        if (*extlconv->decimal_point)
                decimal_point = strdup(extlconv->decimal_point);
        else
--- 1714,1719 ----
---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?

               http://www.postgresql.org/docs/faq

Reply via email to