// // date_format.cxx // logging // // Created by Sam Jaffe on 4/4/19. // #include #include #include #include "logger/exception.h" #include "logger/format.h" #include "logger/logger_fwd.h" #include "logger/logpacket.h" namespace logging { std::string fmt_time(struct timeval round, char const * const fmt) { struct tm time; // Supports localtime when requested, but you can't really test that if (strstr(fmt, "%z") || strstr(fmt, "%Z")) { localtime_r(&round.tv_sec, &time); } else { gmtime_r(&round.tv_sec, &time); } char buf[64] = {'\0'}; std::strftime(buf, sizeof(buf), fmt, &time); return buf; } std::string fmt_time_with_milis(struct timeval round, std::string const & fmt) { char buf[64] = {'\0'}; snprintf(buf, sizeof(buf), fmt.c_str(), round.tv_usec/1000); return fmt_time(round, buf); } string_generator get_date_formatter(std::string fmt) { if (fmt.find("%_ms") != std::string::npos) { size_t pos = 0; while ((pos = fmt.find("%", pos)) != std::string::npos) { fmt.replace(pos, 1, "%%"); pos += 2; } fmt.replace(fmt.find("%%_ms"), 5, "%.03d"); return [=](logpacket const & lp) { return fmt_time_with_milis(lp.time, fmt); }; } else { return [=](logpacket const & lp) { return fmt_time(lp.time, fmt.c_str()); }; } } string_generator parse_date_format_string(char const * str) { char const * const end = strchr(str, '}'); if (end == nullptr) { std::string error_msg{"expected date-format specifier to terminate"}; throw format_parsing_exception{error_msg}; } return get_date_formatter(std::string(str, end)); } }