dt_status_t dt_to_string()

in src/dt.c [669:754]


dt_status_t dt_to_string(const dt_representation_t *representation, const char *fmt,
                         char *str_buffer, size_t str_buffer_size)
{
    struct tm tm = {0};
    dt_status_t status = DT_UNKNOWN_ERROR;
    size_t fmt_len = 0;
    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 str_buffer_eos_pos = 0;
    size_t characters_appended = 0;
    size_t i = 0;

    if (!representation || !fmt || !str_buffer || str_buffer_size <= 0) {
        return DT_INVALID_ARGUMENT;
    }

    // Checking for too long format string
    fmt_len = strlen(fmt);
    if (fmt_len >= sizeof(fmt_buffer)) {
        return DT_OVERFLOW;
    }

    status = dt_representation_to_tm(representation, &tm);
    if (status != DT_OK) {
        return status;
    }

    while (fmt_start_pos < fmt_len) {
        // 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 -> serializing date-time value against the rest of the format string
            characters_appended = strftime(str_buffer + str_buffer_eos_pos, str_buffer_size - str_buffer_eos_pos,
                                           fmt + fmt_start_pos, &tm);

            if ((characters_appended == 0) && (fmt_len > fmt_start_pos) && (fmt_len - fmt_start_pos < str_buffer_size - str_buffer_eos_pos)) {
                // if format string in wrong format, windows std library's function strftime return 0
                str_buffer[str_buffer_eos_pos] = fmt[fmt_start_pos];
                str_buffer_eos_pos++;
                fmt_start_pos++;
                str_buffer[str_buffer_eos_pos] = '\0';
                continue;
            }
            if (characters_appended <= 0) {
                return DT_OVERFLOW;
            }
            str_buffer_eos_pos += characters_appended;
            break;
        } else {
            if (fractional_seconds_format_pos > 0) {
                // Extracting leading data to the buffer and serializing date-time value according this format
                memcpy(fmt_buffer, fmt + fmt_start_pos, fractional_seconds_format_pos);
                fmt_buffer[fractional_seconds_format_pos] = '\0';
                characters_appended = strftime(str_buffer + str_buffer_eos_pos, str_buffer_size - str_buffer_eos_pos,
                                               fmt_buffer, &tm);
                if (characters_appended <= 0) {
                    return DT_OVERFLOW;
                }
                str_buffer_eos_pos += characters_appended;
            }
            fmt_start_pos += (fractional_seconds_format_pos + fractional_seconds_format_length);

            // Serializing fractional seconds
            if (fractional_seconds_precision == 0) {
                fractional_seconds_precision = 9;
            }
            for (i = 0; i < fractional_seconds_precision; ++i) {
                char cur_digit = '\0';
                // Checking for free space in result buffer
                if (str_buffer_eos_pos >= str_buffer_size - 1) {
                    return DT_OVERFLOW;
                }

                cur_digit = (int) floor(representation->nano_second / pow(10, 8 - i)) % 10 + '0';
                str_buffer[str_buffer_eos_pos] = cur_digit;
                ++str_buffer_eos_pos;
            }
            str_buffer[str_buffer_eos_pos] = '\0';
        }
    }
    return DT_OK;
}