From eb738780bf69ca92b8f8d4181d27f196f01b4078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Love=20H=C3=B6rnquist=20=C3=85strand?= Date: Tue, 21 Jun 2005 18:52:37 +0000 Subject: [PATCH] Write a new parse_number function that is possible to limit that amount of numbers used, with this strptime can handle strptime("200505", "%Y%m", &tm); git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@15500 ec53bebd-3082-4978-b11e-865c3cabbd6b --- lib/roken/strptime.c | 104 ++++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 47 deletions(-) diff --git a/lib/roken/strptime.c b/lib/roken/strptime.c index e60d94ec8..8d6fc7383 100644 --- a/lib/roken/strptime.c +++ b/lib/roken/strptime.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Kungliga Tekniska Högskolan + * Copyright (c) 1999, 2003, 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -120,7 +120,41 @@ match_string (const char **buf, const char **strs) } /* - * tm_year is relative this year */ + * Try to match `*buf' to at the most `n' characters and return the + * resulting number in `num'. Returns 0 or an error. Also advance + * buf. + */ + +static int +parse_number (const char **buf, int n, int *num) +{ + char *s, *str; + int i; + + str = malloc(n + 1); + if (str == NULL) + return -1; + + /* skip whitespace */ + for (; **buf != '\0' && isspace((unsigned char)(**buf)); (*buf)++) + ; + + /* parse at least n characters */ + for (i = 0; **buf != '\0' && i < n && isdigit((unsigned char)(**buf)); i++, (*buf)++) + str[i] = **buf; + str[i] = '\0'; + + *num = strtol (str, &s, 10); + free(str); + if (s == str) + return -1; + + return 0; +} + +/* + * tm_year is relative this year + */ const int tm_year_base = 1900; @@ -247,11 +281,9 @@ strptime (const char *buf, const char *format, struct tm *timeptr) timeptr->tm_mon = ret; break; case 'C' : - ret = strtol (buf, &s, 10); - if (s == buf) + if (parse_number(&buf, 2, &ret)) return NULL; timeptr->tm_year = (ret * 100) - tm_year_base; - buf = s; break; case 'c' : abort (); @@ -263,51 +295,43 @@ strptime (const char *buf, const char *format, struct tm *timeptr) break; case 'd' : case 'e' : - ret = strtol (buf, &s, 10); - if (s == buf) + if (parse_number(&buf, 2, &ret)) return NULL; timeptr->tm_mday = ret; - buf = s; break; case 'H' : case 'k' : - ret = strtol (buf, &s, 10); - if (s == buf) + if (parse_number(&buf, 2, &ret)) return NULL; timeptr->tm_hour = ret; - buf = s; break; case 'I' : case 'l' : - ret = strtol (buf, &s, 10); - if (s == buf) + if (parse_number(&buf, 2, &ret)) return NULL; if (ret == 12) timeptr->tm_hour = 0; else timeptr->tm_hour = ret; - buf = s; break; case 'j' : - ret = strtol (buf, &s, 10); - if (s == buf) + if (parse_number(&buf, 3, &ret)) + return NULL; + if (ret == 0) return NULL; timeptr->tm_yday = ret - 1; - buf = s; break; case 'm' : - ret = strtol (buf, &s, 10); - if (s == buf) + if (parse_number(&buf, 2, &ret)) + return NULL; + if (ret == 0) return NULL; timeptr->tm_mon = ret - 1; - buf = s; break; case 'M' : - ret = strtol (buf, &s, 10); - if (s == buf) + if (parse_number(&buf, 2, &ret)) return NULL; timeptr->tm_min = ret; - buf = s; break; case 'n' : while (isspace (*buf)) @@ -336,11 +360,9 @@ strptime (const char *buf, const char *format, struct tm *timeptr) buf = s; break; case 'S' : - ret = strtol (buf, &s, 10); - if (s == buf) + if (parse_number(&buf, 2, &ret)) return NULL; timeptr->tm_sec = ret; - buf = s; break; case 't' : while (isspace (*buf)) @@ -354,39 +376,31 @@ strptime (const char *buf, const char *format, struct tm *timeptr) buf = s; break; case 'u' : - ret = strtol (buf, &s, 10); - if (s == buf) + if (parse_number(&buf, 1, &ret)) + return NULL; + if (ret <= 0) return NULL; timeptr->tm_wday = ret - 1; - buf = s; break; case 'w' : - ret = strtol (buf, &s, 10); - if (s == buf) + if (parse_number(&buf, 1, &ret)) return NULL; timeptr->tm_wday = ret; - buf = s; break; case 'U' : - ret = strtol (buf, &s, 10); - if (s == buf) + if (parse_number(&buf, 2, &ret)) return NULL; set_week_number_sun (timeptr, ret); - buf = s; break; case 'V' : - ret = strtol (buf, &s, 10); - if (s == buf) + if (parse_number(&buf, 2, &ret)) return NULL; set_week_number_mon4 (timeptr, ret); - buf = s; break; case 'W' : - ret = strtol (buf, &s, 10); - if (s == buf) + if (parse_number(&buf, 2, &ret)) return NULL; set_week_number_mon (timeptr, ret); - buf = s; break; case 'x' : s = strptime (buf, "%Y:%m:%d", timeptr); @@ -395,21 +409,17 @@ strptime (const char *buf, const char *format, struct tm *timeptr) buf = s; break; case 'y' : - ret = strtol (buf, &s, 10); - if (s == buf) + if (parse_number(&buf, 2, &ret)) return NULL; if (ret < 70) timeptr->tm_year = 100 + ret; else timeptr->tm_year = ret; - buf = s; break; case 'Y' : - ret = strtol (buf, &s, 10); - if (s == buf) + if (parse_number(&buf, 4, &ret)) return NULL; timeptr->tm_year = ret - tm_year_base; - buf = s; break; case 'Z' : abort ();