in src/dt.c [756:857]
dt_status_t dt_from_string(const char *str, const char *fmt, dt_representation_t *representation)
{
struct tm tm = {0};
dt_status_t status = DT_UNKNOWN_ERROR;
size_t fmt_len = 0;
const char *str_ptr = str;
char fmt_buffer[255] = {0};
int fractional_seconds_format_pos = 0;
size_t fmt_start_pos = 0;
size_t fractional_seconds_format_length = 0;
size_t fractional_seconds_precision = 0;
size_t fractional_digits_parsed = 0;
unsigned long nano_second = 0;
if (!representation || !str || !fmt) {
return DT_INVALID_ARGUMENT;
}
// Checking for too long format string
fmt_len = strlen(fmt);
if (fmt_len >= sizeof(fmt_buffer)) {
return DT_OVERFLOW;
}
while (1) {
if (fmt_start_pos < fmt_len) {
// There is some data in format string
if (*str_ptr == '\0') {
// No data to parse
return DT_INVALID_ARGUMENT;
}
} else {
// Format string has been expired
if (*str_ptr != '\0') {
// There is some extra data to parse
return DT_INVALID_ARGUMENT;
} else {
// No data to parse
break;
}
}
// Searching for fractional format placeholder
fractional_seconds_format_pos = dt_parse_fractional_seconds_format(fmt + fmt_start_pos,
&fractional_seconds_format_length, &fractional_seconds_precision);
if (fractional_seconds_format_pos < 0) {
// No fractional seconds placeholder found -> parsing the rest of the string against the rest of format
str_ptr = strptime(str_ptr, fmt + fmt_start_pos, &tm); // FIXME: Warning on UNIX platform!
if (str_ptr == NULL) {
// Parsing error occured
return DT_INVALID_ARGUMENT;
}
if (*str_ptr != '\0') {
// There is some extra data to parse
return DT_INVALID_ARGUMENT;
}
break;
} else {
if (fractional_seconds_format_pos > 0) {
// Extracting leading format data to the buffer and parsing date-time value according this format
memcpy(fmt_buffer, fmt + fmt_start_pos, fractional_seconds_format_pos);
fmt_buffer[fractional_seconds_format_pos] = '\0';
str_ptr = strptime(str_ptr, fmt_buffer, &tm); // FIXME: Warning on UNIX platform!
if (str_ptr == NULL) {
// Parsing error occured
return DT_INVALID_ARGUMENT;
}
}
fmt_start_pos += (fractional_seconds_format_pos + fractional_seconds_format_length);
// Parsing fractional seconds
if (fractional_seconds_precision == 0) {
fractional_seconds_precision = 9;
}
nano_second = 0;
fractional_digits_parsed = 0;
while (fractional_digits_parsed < fractional_seconds_precision) {
if (!isdigit(*str_ptr)) {
if (fractional_digits_parsed == 0) {
// Parsing error occured
return DT_INVALID_ARGUMENT;
}
break;
}
nano_second *= 10UL;
nano_second += (unsigned long) * str_ptr - '0';
++str_ptr;
++fractional_digits_parsed;
}
nano_second *= (unsigned long)pow(10, 9 - fractional_digits_parsed);
}
}
status = dt_tm_to_representation(&tm, nano_second, representation);
if (status != DT_OK) {
return status;
}
return DT_OK;
}