Re: thousands comma numeric formatting in psql - Mailing list pgsql-patches
From | Bruce Momjian |
---|---|
Subject | Re: thousands comma numeric formatting in psql |
Date | |
Msg-id | 200507142113.j6ELDhR16663@candle.pha.pa.us Whole thread Raw |
In response to | Re: thousands comma numeric formatting in psql (Tom Lane <tgl@sss.pgh.pa.us>) |
List | pgsql-patches |
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 ----
pgsql-patches by date: