about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2013-08-22 19:27:36 -0400
committerRich Felker <dalias@aerifal.cx>2013-08-22 19:27:36 -0400
commit45849d3dcb886b7dff236c3905fa3e101e85ed71 (patch)
tree859503e28f64fe0ccd8367d429736462700d0218
parentf5e4efc4bd1e11e5bb542d4124ab8ce4d4424c47 (diff)
downloadmusl-45849d3dcb886b7dff236c3905fa3e101e85ed71.tar.gz
musl-45849d3dcb886b7dff236c3905fa3e101e85ed71.tar.xz
musl-45849d3dcb886b7dff236c3905fa3e101e85ed71.zip
more strftime refactoring
make __strftime_fmt_1 return a string (possibly in the caller-provided
temp buffer) rather than writing into the output buffer. this approach
makes more sense when padding to a minimum field width might be
required, and it's also closer to what wcsftime wants.
-rw-r--r--src/time/strftime.c48
1 files changed, 25 insertions, 23 deletions
diff --git a/src/time/strftime.c b/src/time/strftime.c
index 87e87d50..d90b690a 100644
--- a/src/time/strftime.c
+++ b/src/time/strftime.c
@@ -46,15 +46,13 @@ static int week_num(const struct tm *tm)
 
 size_t __strftime_l(char *restrict, size_t, const char *restrict, const struct tm *restrict, locale_t);
 
-int __strftime_fmt_1(char *s, size_t n, int f, const struct tm *tm, locale_t loc)
+const char *__strftime_fmt_1(char (*s)[100], int f, const struct tm *tm, locale_t loc)
 {
 	nl_item item;
 	int val;
 	const char *fmt;
 	size_t l;
 
-	if (n<2) return 0;
-
 	switch (f) {
 	case 'a':
 		item = ABDAY_1 + tm->tm_wday;
@@ -124,9 +122,7 @@ int __strftime_fmt_1(char *s, size_t n, int f, const struct tm *tm, locale_t loc
 		fmt = "%02d";
 		goto number;
 	case 'n':
-		s[0] = '\n';
-		s[1] = 0;
-		return 1;
+		return "\n";
 	case 'p':
 		item = tm->tm_hour >= 12 ? PM_STR : AM_STR;
 		goto nl_strcat;
@@ -141,9 +137,7 @@ int __strftime_fmt_1(char *s, size_t n, int f, const struct tm *tm, locale_t loc
 		fmt = "%02d";
 		goto number;
 	case 't':
-		s[0] = '\t';
-		s[1] = 0;
-		return 1;
+		return "\t";
 	case 'T':
 		fmt = "%H:%M:%S";
 		goto recu_strftime;
@@ -183,43 +177,51 @@ int __strftime_fmt_1(char *s, size_t n, int f, const struct tm *tm, locale_t loc
 		goto number;
 	case 'z':
 		val = -tm->__tm_gmtoff;
-		return snprintf(s, n, "%+.2d%.2d", val/3600, abs(val%3600)/60);
+		snprintf(*s, sizeof *s, "%+.2d%.2d", val/3600, abs(val%3600)/60);
+		return *s;
 	case 'Z':
-		return snprintf(s, n, "%s", tm->__tm_zone);
+		return tm->__tm_zone;
 	case '%':
-		s[0] = '%';
-		s[1] = 0;
-		return 1;
+		return "%";
 	default:
 		return 0;
 	}
 number:
-	return snprintf(s, n, fmt, val);
+	snprintf(*s, sizeof *s, fmt, val);
+	return *s;
 nl_strcat:
-	return snprintf(s, n, "%s", __nl_langinfo_l(item, loc));
+	return __nl_langinfo_l(item, loc);
 nl_strftime:
 	fmt = __nl_langinfo_l(item, loc);
 recu_strftime:
-	return __strftime_l(s, n, fmt, tm, loc);
+	l = __strftime_l(*s, sizeof *s, fmt, tm, loc);
+	if (!l) return 0;
+	return *s;
 }
 
 size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const struct tm *restrict tm, locale_t loc)
 {
 	size_t l, k;
-	for (l=0; *f && l<n; f++) {
+	char buf[100];
+	const char *t;
+	for (l=0; l+1<n; f++) {
+		if (!*f) {
+			s[l] = 0;
+			return l;
+		}
 		if (*f != '%') {
 			s[l++] = *f;
 			continue;
 		}
 		f++;
 		if (*f == 'E' || *f == 'O') f++;
-		k = __strftime_fmt_1(s+l, n-l, *f, tm, loc);
-		if (!k) return 0;
+		t = __strftime_fmt_1(&buf, *f, tm, loc);
+		if (!t || (k = strlen(t)) >= n-l)
+			return 0;
+		memcpy(s+l, t, k);
 		l += k;
 	}
-	if (l >= n) return 0;
-	s[l] = 0;
-	return l;
+	return 0;
 }
 
 size_t strftime(char *restrict s, size_t n, const char *restrict f, const struct tm *restrict tm)