1 /* Copyright (C) 2000, 2004, 2008 Free Software Foundation, Inc. 2 This file is part of the GNU C Library. 3 Contributed by Ulrich Drepper <drepper@gnu.org>, 2000. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, write to the Free 17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 18 02111-1307 USA. */ 19 20 /* Look up the value of the next multibyte character and return its numerical 21 value if it is one of the digits known in the locale. If *DECIDED is 22 -1 this means it is not yet decided which form it is and we have to 23 search through all available digits. Otherwise we know which script 24 the digits are from. */ 25 static inline char * 26 outdigit_value (char *s, int n) 27 { 28 const char *outdigit; 29 size_t dlen; 30 31 assert (0 <= n && n <= 9); 32 outdigit = nl_langinfo (_NL_CTYPE_OUTDIGIT0_MB + n); 33 dlen = strlen (outdigit); 34 35 s -= dlen; 36 while (dlen-- > 0) 37 s[dlen] = outdigit[dlen]; 38 39 return s; 40 } 41 42 /* Look up the value of the next multibyte character and return its numerical 43 value if it is one of the digits known in the locale. If *DECIDED is 44 -1 this means it is not yet decided which form it is and we have to 45 search through all available digits. Otherwise we know which script 46 the digits are from. */ 47 static inline wchar_t 48 outdigitwc_value (int n) 49 { 50 assert (0 <= n && n <= 9); 51 52 return nl_langinfo_wc (_NL_CTYPE_OUTDIGIT0_WC + n); 53 } 54 55 static char * 56 _i18n_number_rewrite (char *w, char *rear_ptr, char *end) 57 { 58 char decimal[MB_LEN_MAX + 1]; 59 char thousands[MB_LEN_MAX + 1]; 60 61 /* "to_outpunct" is a map from ASCII decimal point and thousands-sep 62 to their equivalent in locale. This is defined for locales which 63 use extra decimal point and thousands-sep. */ 64 wctrans_t map = wctrans ("to_outpunct"); 65 wint_t wdecimal = towctrans (L_('.'), map); 66 wint_t wthousands = towctrans (L_(','), map); 67 68 if (__builtin_expect (map != NULL, 0)) 69 { 70 mbstate_t state; 71 memset (&state, '\0', sizeof (state)); 72 73 size_t n = wcrtomb (decimal, wdecimal, &state); 74 if (n == (size_t) -1) 75 memcpy (decimal, ".", 2); 76 else 77 decimal[n] = '\0'; 78 79 memset (&state, '\0', sizeof (state)); 80 81 n = wcrtomb (thousands, wthousands, &state); 82 if (n == (size_t) -1) 83 memcpy (thousands, ",", 2); 84 else 85 thousands[n] = '\0'; 86 } 87 88 /* Copy existing string so that nothing gets overwritten. */ 89 char *src; 90 int use_alloca = (rear_ptr - w) < 4096; 91 if (__builtin_expect (use_alloca, 1)) 92 src = (char *) alloca (rear_ptr - w); 93 else 94 { 95 src = (char *) malloc (rear_ptr - w); 96 if (src == NULL) 97 /* If we cannot allocate the memory don't rewrite the string. 98 It is better than nothing. */ 99 return w; 100 } 101 102 memcpy (src, w, rear_ptr - w); 103 char *s = src + (rear_ptr - w); 104 105 w = end; 106 107 /* Process all characters in the string. */ 108 while (--s >= src) 109 { 110 if (*s >= '0' && *s <= '9') 111 { 112 if (sizeof (char) == 1) 113 w = (char *) outdigit_value ((char *) w, *s - '0'); 114 else 115 *--w = (char) outdigitwc_value (*s - '0'); 116 } 117 else if (__builtin_expect (map == NULL, 1) || (*s != '.' && *s != ',')) 118 *--w = *s; 119 else 120 { 121 if (sizeof (char) == 1) 122 { 123 const char *outpunct = *s == '.' ? decimal : thousands; 124 size_t dlen = strlen (outpunct); 125 126 w -= dlen; 127 while (dlen-- > 0) 128 w[dlen] = outpunct[dlen]; 129 } 130 else 131 *--w = *s == '.' ? (char) wdecimal : (char) wthousands; 132 } 133 } 134 135 if (! use_alloca) 136 free (src); 137 138 return w; 139 } 140