summaryrefslogtreecommitdiff
path: root/src/time/wcsftime.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2013-08-22 22:36:19 -0400
committerRich Felker <dalias@aerifal.cx>2013-08-22 22:36:19 -0400
commitfc48ceee773e851d8be675f25be4f476646aa99e (patch)
tree477baeae7456a65fefdf6f9bb0720f3562cbbb53 /src/time/wcsftime.c
parent33413cdd25c58f0e57061e0a3cb7a29d492ba785 (diff)
downloadmusl-fc48ceee773e851d8be675f25be4f476646aa99e.tar.gz
musl-fc48ceee773e851d8be675f25be4f476646aa99e.tar.bz2
musl-fc48ceee773e851d8be675f25be4f476646aa99e.tar.xz
musl-fc48ceee773e851d8be675f25be4f476646aa99e.zip
add strftime and wcsftime field widths
at present, since POSIX requires %F to behave as %+4Y-%m-%d and ISO C requires %F to behave as %Y-%m-%d, the default behavior for %Y has been changed to match %+4Y. this seems to be the only way to conform to the requirements of both standards, and it does not affect years prior to the year 10000. depending on the outcome of interpretations from the standards bodies, this may be adjusted at some point.
Diffstat (limited to 'src/time/wcsftime.c')
-rw-r--r--src/time/wcsftime.c70
1 files changed, 49 insertions, 21 deletions
diff --git a/src/time/wcsftime.c b/src/time/wcsftime.c
index 7d9cef00..72af9137 100644
--- a/src/time/wcsftime.c
+++ b/src/time/wcsftime.c
@@ -4,33 +4,61 @@
#include <locale.h>
#include "libc.h"
-size_t __strftime_l(char *restrict, size_t, const char *restrict, const struct tm *restrict, locale_t);
+const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *tm, locale_t loc);
-size_t __wcsftime_l(wchar_t *restrict wcs, size_t n, const wchar_t *restrict f, const struct tm *restrict tm, locale_t loc)
+size_t __wcsftime_l(wchar_t *restrict s, size_t n, const wchar_t *restrict f, const struct tm *restrict tm, locale_t loc)
{
- size_t k, n0=n;
- char out[100], in[4];
- while (*f) {
- if (!n) return 0;
+ size_t l, k;
+ char buf[100];
+ wchar_t wbuf[100];
+ wchar_t *p;
+ const char *t_mb;
+ const wchar_t *t;
+ int plus;
+ unsigned long width;
+ for (l=0; l+1<n; f++) {
+ if (!*f) {
+ s[l] = 0;
+ return l;
+ }
if (*f != '%') {
- *wcs++ = *f++;
- n--;
+ s[l++] = *f;
continue;
}
- in[2] = in[3] = 0;
- in[0] = *f++;
- if (strchr("EO", (in[1]=*f++)))
- in[2] = *f++;
- k = __strftime_l(out, sizeof out, in, tm, loc);
- if (!k) return 0;
- k = mbsrtowcs(wcs, (const char *[]){out}, n, 0);
- if (k==(size_t)-1) return 0;
- wcs += k;
- n -= k;
+ f++;
+ if ((plus = (*f == '+'))) f++;
+ width = wcstoul(f, &p, 10);
+ if (*p == 'C' || *p == 'F' || *p == 'G' || *p == 'Y') {
+ if (!width && p!=f) width = 1;
+ if (width >= n-l) return 0;
+ } else {
+ width = 0;
+ }
+ f = p;
+ if (*f == 'E' || *f == 'O') f++;
+ t_mb = __strftime_fmt_1(&buf, &k, *f, tm, loc);
+ if (!t_mb) return 0;
+ k = mbstowcs(wbuf, t_mb, sizeof wbuf / sizeof *wbuf);
+ if (k == (size_t)-1) return 0;
+ t = wbuf;
+ if (width) {
+ for (; *t=='+' || *t=='-' || (*t=='0'&&t[1]); t++, k--);
+ width--;
+ if (plus && tm->tm_year >= 10000-1900)
+ s[l++] = '+';
+ else if (tm->tm_year < -1900)
+ s[l++] = '-';
+ else
+ width++;
+ if (width >= n-l) return 0;
+ for (; width > k; width--)
+ s[l++] = '0';
+ }
+ if (k >= n-l) return 0;
+ wmemcpy(s+l, t, k);
+ l += k;
}
- if (!n) return 0;
- *wcs++ = 0;
- return n0-n;
+ return 0;
}
size_t wcsftime(wchar_t *restrict wcs, size_t n, const wchar_t *restrict f, const struct tm *restrict tm)