Change what iso8601_to_nstime() and unix_epoch_to_nstime() return.
Instead of rturning an 8-bit(!) integer giving the number of characters parsed, have them return a pointer to the first character *after* the string that was parsed, similarly to what strto*() (and Wireshark's wrappers for them in wsutil) and strptime() return. This cleans up some code that uses those routines. For the 3GPP 32.423 trace files, we also reject files where there isn't an ISO 8601-format time where we expect there to be one. (Having the string-format date/time routines return NULL on an error means you have to think about what to do on failure.)
This commit is contained in:
parent
e1b885728a
commit
656f00ef29
|
@ -1449,7 +1449,7 @@ main(int argc, char *argv[])
|
|||
nstime_t in_time;
|
||||
|
||||
check_startstop = TRUE;
|
||||
if ((0 < iso8601_to_nstime(&in_time, ws_optarg, ISO8601_DATETIME)) || (0 < unix_epoch_to_nstime(&in_time, ws_optarg))) {
|
||||
if ((NULL != iso8601_to_nstime(&in_time, ws_optarg, ISO8601_DATETIME)) || (NULL != unix_epoch_to_nstime(&in_time, ws_optarg))) {
|
||||
if (opt == 'A') {
|
||||
nstime_copy(&starttime, &in_time);
|
||||
have_starttime = TRUE;
|
||||
|
|
|
@ -246,10 +246,12 @@ absolute_val_from_string(fvalue_t *fv, const char *s, size_t len _U_, char **err
|
|||
return TRUE;
|
||||
|
||||
/* Try ISO 8601 format. */
|
||||
if (iso8601_to_nstime(&fv->value.time, s, ISO8601_DATETIME) == strlen(s))
|
||||
endptr = iso8601_to_nstime(&fv->value.time, s, ISO8601_DATETIME);
|
||||
/* Check whether it parsed all of the string */
|
||||
if (endptr != NULL && *endptr == '\0')
|
||||
return TRUE;
|
||||
|
||||
/* Try other legacy formats. */
|
||||
/* No - try other legacy formats. */
|
||||
memset(&tm, 0, sizeof(tm));
|
||||
/* Let the computer figure out if it's DST. */
|
||||
tm.tm_isdst = -1;
|
||||
|
|
|
@ -1809,15 +1809,15 @@ tvb_get_string_time(tvbuff_t *tvb, const gint offset, const gint length,
|
|||
|
||||
if (*ptr) {
|
||||
if ((encoding & ENC_ISO_8601_DATE_TIME) == ENC_ISO_8601_DATE_TIME) {
|
||||
if ((num_chars = iso8601_to_nstime(ns, ptr, ISO8601_DATETIME))) {
|
||||
end = ptr + num_chars;
|
||||
} else {
|
||||
if (!(end = iso8601_to_nstime(ns, ptr, ISO8601_DATETIME))) {
|
||||
|
||||
|
||||
goto fail;
|
||||
}
|
||||
} else if ((encoding & ENC_ISO_8601_DATE_TIME_BASIC) == ENC_ISO_8601_DATE_TIME_BASIC) {
|
||||
if ((num_chars = iso8601_to_nstime(ns, ptr, ISO8601_DATETIME_BASIC))) {
|
||||
end = ptr + num_chars;
|
||||
} else {
|
||||
if (!(end = iso8601_to_nstime(ns, ptr, ISO8601_DATETIME_BASIC))) {
|
||||
|
||||
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -47,7 +47,7 @@ static gboolean eri_enb_log_get_packet(FILE_T fh, wtap_rec* rec,
|
|||
length = length - 1;
|
||||
}
|
||||
|
||||
if (0 < iso8601_to_nstime(&packet_time, line+1, ISO8601_DATETIME)) {
|
||||
if (NULL != iso8601_to_nstime(&packet_time, line+1, ISO8601_DATETIME)) {
|
||||
rec->ts.secs = packet_time.secs;
|
||||
rec->ts.nsecs = packet_time.nsecs;
|
||||
rec->presence_flags |= WTAP_HAS_TS;
|
||||
|
|
|
@ -652,7 +652,8 @@ nettrace_3gpp_32_423_file_open(wtap *wth, int *err, gchar **err_info)
|
|||
{
|
||||
char magic_buf[MAGIC_BUF_SIZE+1];
|
||||
int bytes_read;
|
||||
char *curr_pos;
|
||||
const char *curr_pos;
|
||||
nstime_t start_time;
|
||||
nettrace_3gpp_32_423_file_info_t *file_info;
|
||||
gint64 start_offset;
|
||||
|
||||
|
@ -689,10 +690,15 @@ nettrace_3gpp_32_423_file_open(wtap *wth, int *err, gchar **err_info)
|
|||
return WTAP_OPEN_NOT_MINE;
|
||||
}
|
||||
curr_pos += CLEN(c_begin_time);
|
||||
/* Next we expect an ISO 8601-format time */
|
||||
curr_pos = iso8601_to_nstime(&start_time, curr_pos, ISO8601_DATETIME);
|
||||
if (!curr_pos) {
|
||||
return WTAP_OPEN_NOT_MINE;
|
||||
}
|
||||
|
||||
/* Ok it's our file. From here we'll need to free memory */
|
||||
file_info = g_new0(nettrace_3gpp_32_423_file_info_t, 1);
|
||||
curr_pos += iso8601_to_nstime(&file_info->start_time, curr_pos, ISO8601_DATETIME);
|
||||
file_info->start_time = start_time;
|
||||
file_info->start_offset = start_offset + (curr_pos - magic_buf);
|
||||
file_info->buffer = g_byte_array_sized_new(RINGBUFFER_START_SIZE);
|
||||
g_byte_array_append(file_info->buffer, curr_pos, (guint)(bytes_read - (curr_pos - magic_buf)));
|
||||
|
|
|
@ -277,7 +277,8 @@ nsfiletime_to_nstime(nstime_t *nstime, guint64 nsfiletime)
|
|||
* parses a character string for a date and time given in
|
||||
* ISO 8601 date-time format (eg: 2014-04-07T05:41:56.782+00:00)
|
||||
* and converts to an nstime_t
|
||||
* returns number of chars parsed on success, or 0 on failure
|
||||
* returns pointer to the first character after the last character
|
||||
* parsed on success, or NULL on failure
|
||||
*
|
||||
* NB. ISO 8601 is actually a lot more flexible than the above format,
|
||||
* much to a developer's chagrin. The "basic format" is distinguished from
|
||||
|
@ -299,7 +300,7 @@ nsfiletime_to_nstime(nstime_t *nstime, guint64 nsfiletime)
|
|||
* YYYY-Www-D, YYYY-DDD, etc. For a relatively easy introduction to
|
||||
* these formats, see wikipedia: https://en.wikipedia.org/wiki/ISO_8601
|
||||
*/
|
||||
guint8
|
||||
const char *
|
||||
iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format)
|
||||
{
|
||||
struct tm tm;
|
||||
|
@ -308,8 +309,6 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format)
|
|||
guint frac = 0;
|
||||
gint off_hr = 0;
|
||||
gint off_min = 0;
|
||||
guint8 ret_val = 0;
|
||||
const char *start = ptr;
|
||||
char sign = '\0';
|
||||
gboolean has_separator = FALSE;
|
||||
gboolean have_offset = FALSE;
|
||||
|
@ -322,7 +321,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format)
|
|||
* separator. */
|
||||
for (n_scanned = 0; n_scanned < 4; n_scanned++) {
|
||||
if (!g_ascii_isdigit(*ptr)) {
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
tm.tm_year *= 10;
|
||||
tm.tm_year += *ptr++ - '0';
|
||||
|
@ -330,7 +329,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format)
|
|||
if (*ptr == '-') {
|
||||
switch (format) {
|
||||
case ISO8601_DATETIME_BASIC:
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
case ISO8601_DATETIME:
|
||||
case ISO8601_DATETIME_AUTO:
|
||||
|
@ -341,7 +340,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format)
|
|||
} else if (g_ascii_isdigit(*ptr)) {
|
||||
switch (format) {
|
||||
case ISO8601_DATETIME:
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
case ISO8601_DATETIME_BASIC:
|
||||
case ISO8601_DATETIME_AUTO:
|
||||
|
@ -349,7 +348,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format)
|
|||
has_separator = FALSE;
|
||||
};
|
||||
} else {
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tm.tm_year -= 1900; /* struct tm expects number of years since 1900 */
|
||||
|
@ -375,7 +374,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format)
|
|||
ptr += n_chars;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (*ptr == 'T' || *ptr == ' ') {
|
||||
|
@ -388,7 +387,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format)
|
|||
/* Allow no separator between date and time iff we have no
|
||||
separator between units. (Some extended formats may negotiate
|
||||
no separator here, so this could be changed.) */
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Now we're on to the time part. We'll require a minimum of hours and
|
||||
|
@ -403,7 +402,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format)
|
|||
}
|
||||
else {
|
||||
/* didn't get hours and minutes */
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Test for (whole) seconds */
|
||||
|
@ -413,7 +412,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format)
|
|||
if (1 > sscanf(ptr, has_separator ? ":%2u%n" : "%2u%n",
|
||||
&tm.tm_sec, &n_chars)) {
|
||||
/* Couldn't get them */
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
ptr += n_chars;
|
||||
|
||||
|
@ -453,7 +452,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format)
|
|||
/* Validate what we got so far. mktime() doesn't care about strange
|
||||
values but we should at least start with something valid */
|
||||
if (!tm_is_valid(&tm)) {
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check for a time zone offset */
|
||||
|
@ -508,8 +507,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format)
|
|||
nstime->secs = mktime(&tm);
|
||||
}
|
||||
nstime->nsecs = frac;
|
||||
ret_val = (guint)(ptr-start);
|
||||
return ret_val;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -518,11 +516,12 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format)
|
|||
* a floating point number containing a Unix epoch date-time
|
||||
* format (e.g. 1600000000.000 for Sun Sep 13 05:26:40 AM PDT 2020)
|
||||
* and converts to an nstime_t
|
||||
* returns number of chars parsed on success, or 0 on failure
|
||||
* returns pointer to the first character after the last character
|
||||
* parsed on success, or NULL on failure
|
||||
*
|
||||
* Reference: https://en.wikipedia.org/wiki/Unix_time
|
||||
*/
|
||||
guint8
|
||||
const char *
|
||||
unix_epoch_to_nstime(nstime_t *nstime, const char *ptr)
|
||||
{
|
||||
gint64 secs;
|
||||
|
@ -530,8 +529,6 @@ unix_epoch_to_nstime(nstime_t *nstime, const char *ptr)
|
|||
|
||||
gint n_chars = 0;
|
||||
guint frac = 0;
|
||||
guint8 ret_val = 0;
|
||||
const char *start = ptr;
|
||||
|
||||
nstime_set_unset(nstime);
|
||||
|
||||
|
@ -540,18 +537,18 @@ unix_epoch_to_nstime(nstime_t *nstime, const char *ptr)
|
|||
* might be 64-bit.
|
||||
*/
|
||||
if (!ws_strtoi64(ptr, &ptr_new, &secs)) {
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* For now, reject times before the Epoch. */
|
||||
if (secs < 0) {
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Make sure it fits. */
|
||||
nstime->secs = (time_t) secs;
|
||||
if (nstime->secs != secs) {
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Now let's test for fractional seconds */
|
||||
|
@ -583,10 +580,7 @@ unix_epoch_to_nstime(nstime_t *nstime, const char *ptr)
|
|||
frac = 0;
|
||||
}
|
||||
nstime->nsecs = frac;
|
||||
|
||||
/* return pointer shift */
|
||||
ret_val = (guint)(ptr_new-start);
|
||||
return ret_val;
|
||||
return ptr_new;
|
||||
}
|
||||
|
||||
size_t nstime_to_iso8601(char *buf, size_t buf_size, const nstime_t *nstime)
|
||||
|
|
|
@ -129,15 +129,15 @@ typedef enum {
|
|||
ISO8601_DATETIME_AUTO, /** Autodetect the presence of separators */
|
||||
} iso8601_fmt_e;
|
||||
|
||||
/** parse an ISO 8601 format datetime string to nstime, returns number of
|
||||
chars parsed on success, 0 on failure.
|
||||
/** parse an ISO 8601 format datetime string to nstime, returns pointer
|
||||
to the first character after the last character, NULL on failure
|
||||
Note that nstime is set to unset in the case of failure */
|
||||
WS_DLL_PUBLIC guint8 iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format);
|
||||
WS_DLL_PUBLIC const char * iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format);
|
||||
|
||||
/** parse an Unix epoch timestamp format datetime string to nstime, returns
|
||||
number of chars parsed on success, 0 on failure.
|
||||
pointer to the first character after the last character, NULL on failure
|
||||
Note that nstime is set to unset in the case of failure */
|
||||
WS_DLL_PUBLIC guint8 unix_epoch_to_nstime(nstime_t *nstime, const char *ptr);
|
||||
WS_DLL_PUBLIC const char * unix_epoch_to_nstime(nstime_t *nstime, const char *ptr);
|
||||
|
||||
#define NSTIME_ISO8601_BUFSIZE sizeof("YYYY-MM-DDTHH:MM:SS.123456789Z")
|
||||
|
||||
|
|
|
@ -576,7 +576,7 @@ static void test_int64_to_str_back(void)
|
|||
void test_nstime_from_iso8601(void)
|
||||
{
|
||||
char *str;
|
||||
size_t chars;
|
||||
const char *endp;
|
||||
nstime_t result, expect;
|
||||
struct tm tm1;
|
||||
|
||||
|
@ -593,8 +593,9 @@ void test_nstime_from_iso8601(void)
|
|||
str = "2013-05-30T23:45:25.349124";
|
||||
expect.secs = mktime(&tm1);
|
||||
expect.nsecs = 349124 * 1000;
|
||||
chars = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO);
|
||||
g_assert_cmpuint(chars, ==, strlen(str));
|
||||
endp = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO);
|
||||
g_assert_nonnull(endp);
|
||||
g_assert(*endp == '\0');
|
||||
g_assert_cmpint(result.secs, ==, expect.secs);
|
||||
g_assert_cmpint(result.nsecs, ==, expect.nsecs);
|
||||
|
||||
|
@ -602,8 +603,9 @@ void test_nstime_from_iso8601(void)
|
|||
str = "2013-05-30T23:45:25.349124Z";
|
||||
expect.secs = mktime_utc(&tm1);
|
||||
expect.nsecs = 349124 * 1000;
|
||||
chars = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO);
|
||||
g_assert_cmpuint(chars, ==, strlen(str));
|
||||
endp = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO);
|
||||
g_assert_nonnull(endp);
|
||||
g_assert(*endp == '\0');
|
||||
g_assert_cmpint(result.secs, ==, expect.secs);
|
||||
g_assert_cmpint(result.nsecs, ==, expect.nsecs);
|
||||
|
||||
|
@ -611,8 +613,9 @@ void test_nstime_from_iso8601(void)
|
|||
str = "2013-05-30T23:45:25.349124+01:00";
|
||||
expect.secs = mktime_utc(&tm1) - 1 * 60 * 60;
|
||||
expect.nsecs = 349124 * 1000;
|
||||
chars = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO);
|
||||
g_assert_cmpuint(chars, ==, strlen(str));
|
||||
endp = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO);
|
||||
g_assert_nonnull(endp);
|
||||
g_assert(*endp == '\0');
|
||||
g_assert_cmpint(result.secs, ==, expect.secs);
|
||||
g_assert_cmpint(result.nsecs, ==, expect.nsecs);
|
||||
|
||||
|
@ -620,8 +623,9 @@ void test_nstime_from_iso8601(void)
|
|||
str = "2013-05-30T23:45:25.349124+0100";
|
||||
expect.secs = mktime_utc(&tm1) - 1 * 60 * 60;
|
||||
expect.nsecs = 349124 * 1000;
|
||||
chars = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO);
|
||||
g_assert_cmpuint(chars, ==, strlen(str));
|
||||
endp = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO);
|
||||
g_assert_nonnull(endp);
|
||||
g_assert(*endp == '\0');
|
||||
g_assert_cmpint(result.secs, ==, expect.secs);
|
||||
g_assert_cmpint(result.nsecs, ==, expect.nsecs);
|
||||
|
||||
|
@ -629,8 +633,9 @@ void test_nstime_from_iso8601(void)
|
|||
str = "2013-05-30T23:45:25.349124+01";
|
||||
expect.secs = mktime_utc(&tm1) - 1 * 60 * 60;
|
||||
expect.nsecs = 349124 * 1000;
|
||||
chars = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO);
|
||||
g_assert_cmpuint(chars, ==, strlen(str));
|
||||
endp = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO);
|
||||
g_assert_nonnull(endp);
|
||||
g_assert(*endp == '\0');
|
||||
g_assert_cmpint(result.secs, ==, expect.secs);
|
||||
g_assert_cmpint(result.nsecs, ==, expect.nsecs);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue