Skip to content

Commit

Permalink
testing precision
Browse files Browse the repository at this point in the history
  • Loading branch information
xanthospap committed Nov 7, 2023
1 parent 69dfcab commit 2685ced
Show file tree
Hide file tree
Showing 10 changed files with 648 additions and 164 deletions.
151 changes: 151 additions & 0 deletions src/datetime_io_core.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
#include "datetime_io_core.hpp"
#include <cctype>
#include <charconv>
#include <cstdio>

inline const char *skipws(const char *line) noexcept {
const char *c = line;
while (*c && (*c == ' ' || *c == '/' || *c == '-' || *c == 'T' || *c == ':'))
++c;
return c;
}

/** @brief Count decimal digits in a float
*
* Examples:
* assert(count_decimal_digits(".123456789") == 9);
* assert(count_decimal_digits(" .123456789") == 9);
* assert(count_decimal_digits("12.123456789") == 9);
* assert(count_decimal_digits("12.123456789.123") == 9);
* assert(count_decimal_digits("12.123456789.A23") == 9);
* assert(count_decimal_digits("12.123456789EA23") == 9);
*/
inline int count_decimal_digits(const char *fltstr) noexcept {
/* go to decimal part */
while (fltstr && *fltstr != '.')
++fltstr;
if (fltstr && *fltstr == '.') {
/* count digits */
++fltstr;
const char *dgtc = fltstr;
while (std::isdigit(*dgtc))
++dgtc;
return (dgtc - fltstr);
} else {
/* no decimal digits */
return 0;
}
}

int dso::datetime_io_core::get_two_ints(const char *str, int *ints,
int max_chars,
const char **end) noexcept {
if (end)
*end = str;
const char *start = skipws(str);
const char *c = str;

/* resolve the three ints */
for (int i = 0; i < 2; ++i) {
auto tres = std::from_chars(skipws(c), start + max_chars, ints[i]);
if (tres.ec != std::errc{}) {
return i + 1;
}
c = tres.ptr;
}

/* assign pointer to first non-parsed character */
if (end)
*end = c;

return 0;
}

int dso::datetime_io_core::get_three_ints(const char *str, int *ints,
int max_chars,
const char **end) noexcept {
if (end)
*end = str;
const char *c = str;
const char *start = skipws(str);

/* resolve the three ints */
for (int i = 0; i < 3; ++i) {
auto tres = std::from_chars(skipws(c), start + max_chars, ints[i]);
if (tres.ec != std::errc{}) {
return i + 1;
}
c = tres.ptr;
}

/* assign pointer to first non-parsed character */
if (end)
*end = c;

return 0;
}

int dso::datetime_io_core::get_three_ints(const char *str, long *ints,
int max_chars,
const char **end) noexcept {
if (end)
*end = str;
const char *c = str;
const char *start = skipws(str);

/* resolve the three long ints */
for (int i = 0; i < 3; ++i) {
auto tres = std::from_chars(skipws(c), start + max_chars, ints[i]);
if (tres.ec != std::errc{}) {
return i + 1;
}
c = tres.ptr;
}

/* assign pointer to first non-parsed character */
if (end)
*end = c;

return 0;
}

int dso::datetime_io_core::get_two_ints_double(const char *str, int *ints,
double &flt, int max_chars,
const char **end) noexcept {
if (end)
*end = str;
const char *c = str;
const char *start = skipws(str);

/* resolve the two ints */
for (int i = 0; i < 2; ++i) {
auto tres = std::from_chars(skipws(c), start + max_chars, ints[i]);
if (tres.ec != std::errc{}) {
return i + 1;
}
c = tres.ptr;
}

/* before parsing the next floating point number, count its decimal digits
* If more than nanoseconds, issue a warning
*/
if (count_decimal_digits(skipws(c)) > 12) {
fprintf(stderr, "[WARNING] Reading in date with resolution larger than "
"nanoseconds will lead to loss of precision!\n");
fprintf(stderr,
"[WARNING] Date/Time resolved from string \'%s\' (traceback: %s)\n",
str, __func__);
}

/* resolve one double */
auto tres = std::from_chars(skipws(c), start + max_chars, flt);
if (tres.ec != std::errc{}) {
return 3;
}

/* assign pointer to first non-parsed character */
if (end)
*end = tres.ptr;

return 0;
}
18 changes: 17 additions & 1 deletion src/datetime_io_core.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/** Datetime input/output (i.e. read/write) core utilities and definitions.
/** @file
* Datetime input/output (i.e. read/write) core utilities and definitions.
*/

#ifndef __DSO_DATETIME_IO_CORE_HPP__
Expand All @@ -7,6 +8,21 @@
namespace dso {
enum class YMDFormat { YYYYMMDD, DDMMYYYY, YYYYDDD, YYMMDD, DDMMYY };
enum class HMSFormat { HHMMSS, HHMMSSF };

namespace datetime_io_core {
int get_two_ints(const char *str, int *ints, int max_chars,
const char **end) noexcept;

int get_three_ints(const char *str, int *ints, int max_chars,
const char **end) noexcept;

int get_three_ints(const char *str, long *ints, int max_chars,
const char **end) noexcept;

int get_two_ints_double(const char *str, int *ints, double &flt, int max_chars,
const char **end) noexcept;
} /* namespace datetime_io_core */

} /* namespace dso */

#endif
Loading

0 comments on commit 2685ced

Please sign in to comment.