Changeset View
Changeset View
Standalone View
Standalone View
head/lib/libc/stdlib/strfmon.c
Show First 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | #define GRPCPY(howmany) do { \ | ||||
int i = howmany; \ | int i = howmany; \ | ||||
while (i-- > 0) { \ | while (i-- > 0) { \ | ||||
avalue_size--; \ | avalue_size--; \ | ||||
*--bufend = *(avalue+avalue_size+padded); \ | *--bufend = *(avalue+avalue_size+padded); \ | ||||
} \ | } \ | ||||
} while (0) | } while (0) | ||||
#define GRPSEP do { \ | #define GRPSEP do { \ | ||||
*--bufend = thousands_sep; \ | bufend -= thousands_sep_size; \ | ||||
memcpy(bufend, thousands_sep, thousands_sep_size); \ | |||||
groups++; \ | groups++; \ | ||||
} while (0) | } while (0) | ||||
static void __setup_vars(int, char *, char *, char *, char **); | static void __setup_vars(int, char *, char *, char *, char **); | ||||
static int __calc_left_pad(int, char *); | static int __calc_left_pad(int, char *); | ||||
static char *__format_grouped_double(double, int *, int, int, int); | static char *__format_grouped_double(double, int *, int, int, int); | ||||
static ssize_t | static ssize_t | ||||
▲ Show 20 Lines • Show All 411 Lines • ▼ Show 20 Lines | while (size > (int)*grouping) { | ||||
if (*grouping == 0) { | if (*grouping == 0) { | ||||
chars += (size - 1) / *(grouping - 1); | chars += (size - 1) / *(grouping - 1); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
return (chars); | return (chars); | ||||
} | } | ||||
/* convert double to ASCII */ | /* convert double to locale-encoded string */ | ||||
static char * | static char * | ||||
__format_grouped_double(double value, int *flags, | __format_grouped_double(double value, int *flags, | ||||
int left_prec, int right_prec, int pad_char) { | int left_prec, int right_prec, int pad_char) { | ||||
char *rslt; | char *rslt; | ||||
char *avalue; | char *avalue; | ||||
int avalue_size; | int avalue_size; | ||||
size_t bufsize; | size_t bufsize; | ||||
char *bufend; | char *bufend; | ||||
int padded; | int padded; | ||||
struct lconv *lc = localeconv(); | struct lconv *lc = localeconv(); | ||||
char *grouping; | char *grouping; | ||||
char decimal_point; | const char *decimal_point; | ||||
char thousands_sep; | const char *thousands_sep; | ||||
size_t decimal_point_size; | |||||
size_t thousands_sep_size; | |||||
int groups = 0; | int groups = 0; | ||||
grouping = lc->mon_grouping; | grouping = lc->mon_grouping; | ||||
decimal_point = *lc->mon_decimal_point; | decimal_point = lc->mon_decimal_point; | ||||
if (decimal_point == '\0') | if (*decimal_point == '\0') | ||||
decimal_point = *lc->decimal_point; | decimal_point = lc->decimal_point; | ||||
thousands_sep = *lc->mon_thousands_sep; | thousands_sep = lc->mon_thousands_sep; | ||||
if (thousands_sep == '\0') | if (*thousands_sep == '\0') | ||||
thousands_sep = *lc->thousands_sep; | thousands_sep = lc->thousands_sep; | ||||
decimal_point_size = strlen(decimal_point); | |||||
thousands_sep_size = strlen(thousands_sep); | |||||
/* fill left_prec with default value */ | /* fill left_prec with default value */ | ||||
if (left_prec == -1) | if (left_prec == -1) | ||||
left_prec = 0; | left_prec = 0; | ||||
/* fill right_prec with default value */ | /* fill right_prec with default value */ | ||||
if (right_prec == -1) { | if (right_prec == -1) { | ||||
if (*flags & USE_INTL_CURRENCY) | if (*flags & USE_INTL_CURRENCY) | ||||
right_prec = lc->int_frac_digits; | right_prec = lc->int_frac_digits; | ||||
Show All 9 Lines | __format_grouped_double(double value, int *flags, | ||||
/* convert to string */ | /* convert to string */ | ||||
avalue_size = asprintf(&avalue, "%*.*f", left_prec + right_prec + 1, | avalue_size = asprintf(&avalue, "%*.*f", left_prec + right_prec + 1, | ||||
right_prec, value); | right_prec, value); | ||||
if (avalue_size < 0) | if (avalue_size < 0) | ||||
return (NULL); | return (NULL); | ||||
/* make sure that we've enough space for result string */ | /* make sure that we've enough space for result string */ | ||||
bufsize = avalue_size * 2 + 1; | bufsize = avalue_size * (1 + thousands_sep_size) + decimal_point_size + | ||||
1; | |||||
rslt = calloc(1, bufsize); | rslt = calloc(1, bufsize); | ||||
if (rslt == NULL) { | if (rslt == NULL) { | ||||
free(avalue); | free(avalue); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
bufend = rslt + bufsize - 1; /* reserve space for trailing '\0' */ | bufend = rslt + bufsize - 1; /* reserve space for trailing '\0' */ | ||||
/* skip spaces at beginning */ | /* skip spaces at beginning */ | ||||
padded = 0; | padded = 0; | ||||
while (avalue[padded] == ' ') { | while (avalue[padded] == ' ') { | ||||
padded++; | padded++; | ||||
avalue_size--; | avalue_size--; | ||||
} | } | ||||
if (right_prec > 0) { | if (right_prec > 0) { | ||||
bufend -= right_prec; | bufend -= right_prec; | ||||
memcpy(bufend, avalue + avalue_size+padded-right_prec, | memcpy(bufend, avalue + avalue_size+padded-right_prec, | ||||
right_prec); | right_prec); | ||||
*--bufend = decimal_point; | bufend -= decimal_point_size; | ||||
memcpy(bufend, decimal_point, decimal_point_size); | |||||
avalue_size -= (right_prec + 1); | avalue_size -= (right_prec + 1); | ||||
} | } | ||||
if ((*flags & NEED_GROUPING) && | if ((*flags & NEED_GROUPING) && | ||||
thousands_sep != '\0' && /* XXX: need investigation */ | thousands_sep_size > 0 && /* XXX: need investigation */ | ||||
*grouping != CHAR_MAX && | *grouping != CHAR_MAX && | ||||
*grouping > 0) { | *grouping > 0) { | ||||
while (avalue_size > (int)*grouping) { | while (avalue_size > (int)*grouping) { | ||||
GRPCPY(*grouping); | GRPCPY(*grouping); | ||||
GRPSEP; | GRPSEP; | ||||
grouping++; | grouping++; | ||||
/* no more grouping ? */ | /* no more grouping ? */ | ||||
Show All 11 Lines | if ((*flags & NEED_GROUPING) && | ||||
} | } | ||||
if (avalue_size != 0) | if (avalue_size != 0) | ||||
GRPCPY(avalue_size); | GRPCPY(avalue_size); | ||||
padded -= groups; | padded -= groups; | ||||
} else { | } else { | ||||
bufend -= avalue_size; | bufend -= avalue_size; | ||||
memcpy(bufend, avalue+padded, avalue_size); | memcpy(bufend, avalue+padded, avalue_size); | ||||
/* decrease assumed $decimal_point */ | |||||
if (right_prec == 0) | if (right_prec == 0) | ||||
padded--; /* decrease assumed $decimal_point */ | padded -= decimal_point_size; | ||||
} | } | ||||
/* do padding with pad_char */ | /* do padding with pad_char */ | ||||
if (padded > 0) { | if (padded > 0) { | ||||
bufend -= padded; | bufend -= padded; | ||||
memset(bufend, pad_char, padded); | memset(bufend, pad_char, padded); | ||||
} | } | ||||
bufsize = bufsize - (bufend - rslt) + 1; | bufsize = bufsize - (bufend - rslt) + 1; | ||||
memmove(rslt, bufend, bufsize); | memmove(rslt, bufend, bufsize); | ||||
free(avalue); | free(avalue); | ||||
return (rslt); | return (rslt); | ||||
} | } |