Get rid of some places that handled specific timestamp resolutions.

Replace them with tables supporting everything from seconds to
nanoseconds, or with code that calculates 10^{resolution}.
This commit is contained in:
Guy Harris 2023-09-12 17:53:24 -07:00
parent e1c5a055f9
commit 151b85c45e
5 changed files with 247 additions and 223 deletions

View File

@ -972,8 +972,15 @@ get_frame_timestamp_precision(const frame_data *fd)
tsprecision = fd->tsprec;
else if (tsprecision < 0)
ws_assert_not_reached();
if (tsprecision > 9)
tsprecision = 9;
/*
* Time stamp precision values higher than the maximum
* precision we support can't be handled. Just display
* those times with the maximum precision we support.
*/
if (tsprecision > WS_TSPREC_MAX)
tsprecision = WS_TSPREC_MAX;
return tsprecision;
}
@ -984,11 +991,18 @@ get_default_timestamp_precision(void)
tsprecision = timestamp_get_precision();
if (tsprecision == TS_PREC_AUTO)
tsprecision = 9;
tsprecision = WS_TSPREC_MAX; /* default to the maximum precision we support */
else if (tsprecision < 0)
ws_assert_not_reached();
if (tsprecision > 9)
tsprecision = 9;
/*
* Time stamp precision values higher than the maximum
* precision we support can't be handled. Just display
* those times with the maximum precision we support.
*/
if (tsprecision > WS_TSPREC_MAX)
tsprecision = WS_TSPREC_MAX;
return tsprecision;
}

View File

@ -434,6 +434,97 @@ get_column_format_matches(gboolean *fmt_list, const gint format) {
}
}
/*
* These tables are indexed by the number of digits of precision for
* time stamps; all TS_PREC_FIXED_ types have values equal to the
* number of digits of precision, and NUM_WS_TSPREC_VALS is the
* total number of such values as there's a one-to-one correspondence
* between WS_TSPREC_ values and TS_PREC_FIXED_ values.
*/
/*
* Strings for YYYY-MM-DD HH:MM:SS.SSSS dates and times.
* (Yes, we know, this has a Y10K problem.)
*/
static const char *ts_ymd[NUM_WS_TSPREC_VALS] = {
"0000-00-00 00:00:00",
"0000-00-00 00:00:00.0",
"0000-00-00 00:00:00.00",
"0000-00-00 00:00:00.000",
"0000-00-00 00:00:00.0000",
"0000-00-00 00:00:00.00000",
"0000-00-00 00:00:00.000000",
"0000-00-00 00:00:00.0000000",
"0000-00-00 00:00:00.00000000",
"0000-00-00 00:00:00.000000000",
};
/*
* Strings for YYYY/DOY HH:MM:SS.SSSS dates and times.
* (Yes, we know, this also has a Y10K problem.)
*/
static const char *ts_ydoy[NUM_WS_TSPREC_VALS] = {
"0000/000 00:00:00",
"0000/000 00:00:00.0",
"0000/000 00:00:00.00",
"0000/000 00:00:00.000",
"0000/000 00:00:00.0000",
"0000/000 00:00:00.00000",
"0000/000 00:00:00.000000",
"0000/000 00:00:00.0000000",
"0000/000 00:00:00.00000000",
"0000/000 00:00:00.000000000",
};
/*
* Strings for HH:MM:SS.SSSS absolute times without dates.
*/
static const char *ts_abstime[NUM_WS_TSPREC_VALS] = {
"00:00:00",
"00:00:00.0",
"00:00:00.00",
"00:00:00.000",
"00:00:00.0000",
"00:00:00.00000",
"00:00:00.000000",
"00:00:00.0000000",
"00:00:00.00000000",
"00:00:00.000000000",
};
/*
* Strings for SSSS.S relative and delta times.
* (Yes, this has s 10,000-seconds problem.)
*/
static const char *ts_rel_delta_time[NUM_WS_TSPREC_VALS] = {
"0000",
"0000.0",
"0000.00",
"0000.000",
"0000.0000",
"0000.00000",
"0000.000000",
"0000.0000000",
"0000.00000000",
"0000.000000000",
};
/*
* Strings for UN*X/POSIX Epoch times.
*/
static const char *ts_epoch_time[NUM_WS_TSPREC_VALS] = {
"0000000000000000000",
"0000000000000000000.0",
"0000000000000000000.00",
"0000000000000000000.000",
"0000000000000000000.0000",
"0000000000000000000.00000",
"0000000000000000000.000000",
"0000000000000000000.0000000",
"0000000000000000000.00000000",
"0000000000000000000.000000000",
};
/* Returns a string representing the longest possible value for
a timestamp column type. */
static const char *
@ -443,136 +534,72 @@ get_timestamp_column_longest_string(const gint type, const gint precision)
switch(type) {
case(TS_ABSOLUTE_WITH_YMD):
case(TS_UTC_WITH_YMD):
switch(precision) {
case(TS_PREC_FIXED_SEC):
return "0000-00-00 00:00:00";
break;
case(TS_PREC_FIXED_DSEC):
return "0000-00-00 00:00:00.0";
break;
case(TS_PREC_FIXED_CSEC):
return "0000-00-00 00:00:00.00";
break;
case(TS_PREC_FIXED_MSEC):
return "0000-00-00 00:00:00.000";
break;
case(TS_PREC_FIXED_USEC):
return "0000-00-00 00:00:00.000000";
break;
case(TS_PREC_FIXED_NSEC):
case(TS_PREC_AUTO): /* Leave enough room for the maximum */
return "0000-00-00 00:00:00.000000000";
break;
default:
ws_assert_not_reached();
}
break;
if(precision == TS_PREC_AUTO) {
/*
* Return the string for the maximum precision, so that
* our caller leaves room for that string.
*/
return ts_ymd[WS_TSPREC_MAX];
} else if(precision >= 0 && precision < NUM_WS_TSPREC_VALS)
return ts_ymd[precision];
else
ws_assert_not_reached();
break;
case(TS_ABSOLUTE_WITH_YDOY):
case(TS_UTC_WITH_YDOY):
switch(precision) {
case(TS_PREC_FIXED_SEC):
return "0000/000 00:00:00";
break;
case(TS_PREC_FIXED_DSEC):
return "0000/000 00:00:00.0";
break;
case(TS_PREC_FIXED_CSEC):
return "0000/000 00:00:00.00";
break;
case(TS_PREC_FIXED_MSEC):
return "0000/000 00:00:00.000";
break;
case(TS_PREC_FIXED_USEC):
return "0000/000 00:00:00.000000";
break;
case(TS_PREC_FIXED_NSEC):
case(TS_PREC_AUTO): /* Leave enough room for the maximum */
return "0000/000 00:00:00.000000000";
break;
default:
ws_assert_not_reached();
}
break;
if(precision == TS_PREC_AUTO) {
/*
* Return the string for the maximum precision, so that
* our caller leaves room for that string.
*/
return ts_ydoy[WS_TSPREC_MAX];
} else if(precision >= 0 && precision < NUM_WS_TSPREC_VALS)
return ts_ydoy[precision];
else
ws_assert_not_reached();
break;
case(TS_ABSOLUTE):
case(TS_UTC):
switch(precision) {
case(TS_PREC_FIXED_SEC):
return "00:00:00";
break;
case(TS_PREC_FIXED_DSEC):
return "00:00:00.0";
break;
case(TS_PREC_FIXED_CSEC):
return "00:00:00.00";
break;
case(TS_PREC_FIXED_MSEC):
return "00:00:00.000";
break;
case(TS_PREC_FIXED_USEC):
return "00:00:00.000000";
break;
case(TS_PREC_FIXED_NSEC):
case(TS_PREC_AUTO): /* Leave enough room for the maximum */
return "00:00:00.000000000";
break;
default:
ws_assert_not_reached();
}
if(precision == TS_PREC_AUTO) {
/*
* Return the string for the maximum precision, so that
* our caller leaves room for that string.
*/
return ts_abstime[WS_TSPREC_MAX];
} else if(precision >= 0 && precision < NUM_WS_TSPREC_VALS)
return ts_abstime[precision];
else
ws_assert_not_reached();
break;
case(TS_RELATIVE): /* fallthrough */
case(TS_DELTA):
case(TS_DELTA_DIS):
switch(precision) {
case(TS_PREC_FIXED_SEC):
return "0000";
break;
case(TS_PREC_FIXED_DSEC):
return "0000.0";
break;
case(TS_PREC_FIXED_CSEC):
return "0000.00";
break;
case(TS_PREC_FIXED_MSEC):
return "0000.000";
break;
case(TS_PREC_FIXED_USEC):
return "0000.000000";
break;
case(TS_PREC_FIXED_NSEC):
case(TS_PREC_AUTO): /* Leave enough room for the maximum */
return "0000.000000000";
break;
default:
ws_assert_not_reached();
}
if(precision == TS_PREC_AUTO) {
/*
* Return the string for the maximum precision, so that
* our caller leaves room for that string.
*/
return ts_rel_delta_time[WS_TSPREC_MAX];
} else if(precision >= 0 && precision < NUM_WS_TSPREC_VALS)
return ts_rel_delta_time[precision];
else
ws_assert_not_reached();
break;
case(TS_EPOCH):
/* This is enough to represent 2^63 (signed 64-bit integer) + fractions */
switch(precision) {
case(TS_PREC_FIXED_SEC):
return "0000000000000000000";
break;
case(TS_PREC_FIXED_DSEC):
return "0000000000000000000.0";
break;
case(TS_PREC_FIXED_CSEC):
return "0000000000000000000.00";
break;
case(TS_PREC_FIXED_MSEC):
return "0000000000000000000.000";
break;
case(TS_PREC_FIXED_USEC):
return "0000000000000000000.000000";
break;
case(TS_PREC_FIXED_NSEC):
case(TS_PREC_AUTO): /* Leave enough room for the maximum */
return "0000000000000000000.000000000";
break;
default:
ws_assert_not_reached();
}
if(precision == TS_PREC_AUTO) {
/*
* Return the string for the maximum precision, so that
* our caller leaves room for that string.
*/
return ts_epoch_time[WS_TSPREC_MAX];
} else if(precision >= 0 && precision < NUM_WS_TSPREC_VALS)
return ts_epoch_time[precision];
else
ws_assert_not_reached();
break;
case(TS_NOT_SET):
/* This should not happen. */
return "0000.000000";
break;
default:

View File

@ -1820,46 +1820,34 @@ text_import_pre_open(wtap_dump_params * const params, int file_type_subtype, con
} else {
wtap_block_add_string_option(int_data, OPT_IDB_NAME, "Fake IF, text2pcap", strlen("Fake IF, text2pcap"));
}
switch (params->tsprec) {
if (params->tsprec >= 0 && params->tsprec <= WS_TSPREC_MAX) {
/*
* This is a valid time precision.
*/
case WTAP_TSPREC_SEC:
int_data_mand->time_units_per_second = 1;
wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 0);
break;
/*
* Compute 10^{params->tsprec}.
*/
int_data_mand->time_units_per_second = 1;
for (int i = 0; i < params->tsprec; i++)
int_data_mand->time_units_per_second *= 10;
case WTAP_TSPREC_DSEC:
int_data_mand->time_units_per_second = 10;
wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 1);
break;
case WTAP_TSPREC_CSEC:
int_data_mand->time_units_per_second = 100;
wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 2);
break;
case WTAP_TSPREC_MSEC:
int_data_mand->time_units_per_second = 1000;
wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 3);
break;
case WTAP_TSPREC_USEC:
int_data_mand->time_units_per_second = 1000000;
/* This is the default, so no need to add an option */
break;
case WTAP_TSPREC_NSEC:
int_data_mand->time_units_per_second = 1000000000;
wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 9);
break;
case WTAP_TSPREC_PER_PACKET:
case WTAP_TSPREC_UNKNOWN:
default:
if (params->tsprec != WTAP_TSPREC_USEC) {
/*
* Don't do this.
* Microsecond precision is the default, so we only
* add an option if the precision isn't microsecond
* precision.
*/
ws_assert_not_reached();
break;
wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, params->tsprec);
}
} else {
/*
* Either WTAP_TSPREC_PER_PACKET, WTAP_TSPREC_UNKNOWN,
* or not a valid precision.
*
* Don't do this.
*/
ws_assert_not_reached();
}
params->idb_inf = g_new(wtapng_iface_descriptions_t,1);

View File

@ -241,46 +241,31 @@ wtap_generate_idb(int encap, int tsprec, int snaplen)
if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(idb);
if_descr_mand->wtap_encap = encap;
if_descr_mand->tsprecision = tsprec;
switch (tsprec) {
case WTAP_TSPREC_SEC:
if_descr_mand->time_units_per_second = 1;
wtap_block_add_uint8_option(idb, OPT_IDB_TSRESOL, 0);
break;
case WTAP_TSPREC_DSEC:
if_descr_mand->time_units_per_second = 10;
wtap_block_add_uint8_option(idb, OPT_IDB_TSRESOL, 1);
break;
case WTAP_TSPREC_CSEC:
if_descr_mand->time_units_per_second = 100;
wtap_block_add_uint8_option(idb, OPT_IDB_TSRESOL, 2);
break;
case WTAP_TSPREC_MSEC:
if_descr_mand->time_units_per_second = 1000;
wtap_block_add_uint8_option(idb, OPT_IDB_TSRESOL, 3);
break;
case WTAP_TSPREC_USEC:
if_descr_mand->time_units_per_second = 1000000;
/* This is the default, so no need to add an option */
break;
case WTAP_TSPREC_NSEC:
if_descr_mand->time_units_per_second = 1000000000;
wtap_block_add_uint8_option(idb, OPT_IDB_TSRESOL, 9);
break;
case WTAP_TSPREC_PER_PACKET:
case WTAP_TSPREC_UNKNOWN:
default:
if (tsprec < 0 || tsprec > WS_TSPREC_MAX) {
/*
* No timestamp precision.
* Either WTAP_TSPREC_PER_PACKET, WTAP_TSPREC_UNKNOWN,
* or not a valid WTAP_TSPREC_ value.
*
* Unknown timestamp precision; use the default of
* microsecond resolution.
*/
if_descr_mand->time_units_per_second = 1000000; /* default microsecond resolution */
break;
tsprec = 6; /* microsecond resolution */
}
/*
* Compute 10^{params->tsprec}.
*/
if_descr_mand->time_units_per_second = 1;
for (int i = 0; i < tsprec; i++)
if_descr_mand->time_units_per_second *= 10;
if (tsprec != WTAP_TSPREC_USEC) {
/*
* Microsecond precision is the default, so we only
* add an option if the precision isn't microsecond
* precision.
*/
wtap_block_add_uint8_option(idb, OPT_IDB_TSRESOL, tsprec);
}
if (snaplen == 0) {
/*
@ -1330,37 +1315,34 @@ wtap_name_to_encap(const char *name)
return -1; /* no such encapsulation type */
}
/*
* For precision values that correspond to a specific precision.
*/
static const char *precnames[NUM_WS_TSPREC_VALS] = {
"seconds",
"100 millisconds (deciseconds)",
"10 milliseconds (centiseconds)",
"milliseconds",
"100 microseconds",
"10 microseconds",
"microseconds",
"100 nanoseconds",
"10 nanoseconds",
"nanoseconds",
};
const char*
wtap_tsprec_string(int tsprec)
{
const char* s;
switch (tsprec) {
case WTAP_TSPREC_PER_PACKET:
s = "per-packet";
break;
case WTAP_TSPREC_SEC:
s = "seconds";
break;
case WTAP_TSPREC_DSEC:
s = "deciseconds";
break;
case WTAP_TSPREC_CSEC:
s = "centiseconds";
break;
case WTAP_TSPREC_MSEC:
s = "milliseconds";
break;
case WTAP_TSPREC_USEC:
s = "microseconds";
break;
case WTAP_TSPREC_NSEC:
s = "nanoseconds";
break;
case WTAP_TSPREC_UNKNOWN:
default:
s = "UNKNOWN";
break;
}
if (tsprec == WTAP_TSPREC_PER_PACKET)
s = "per-packet";
else if (tsprec >= 0 && tsprec < NUM_WS_TSPREC_VALS)
s = precnames[tsprec];
else if (tsprec == WTAP_TSPREC_UNKNOWN)
s = "UNKNOWN";
else
s = "INVALID";
return s;
}

View File

@ -162,6 +162,19 @@ typedef enum {
WS_TSPREC_NSEC = 9
} ws_tsprec_e;
/*
* Maximum time stamp precision supported.
* Note that going beyond nanosecond precision would require expanding
* the fractional part of an nstime_t to 64 bits, and changing code
* that currently only handles second to nanosecond precision.
*/
#define WS_TSPREC_MAX 9
/*
* Total number of valid precision values.
*/
#define NUM_WS_TSPREC_VALS (WS_TSPREC_MAX + 1)
#ifdef __cplusplus
}
#endif /* __cplusplus */