mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-06 18:18:52 +08:00
Rewrite format_common_log
This commit is contained in:
149
src/util.cc
149
src/util.cc
@@ -239,53 +239,6 @@ char *http_date(char *res, time_t t) {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string common_log_date(time_t t) {
|
|
||||||
// 03/Jul/2014:00:19:38 +0900
|
|
||||||
std::string res(26, 0);
|
|
||||||
common_log_date(&res[0], t);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *common_log_date(char *res, time_t t) {
|
|
||||||
struct tm tms;
|
|
||||||
|
|
||||||
if (localtime_r(&t, &tms) == nullptr) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto p = res;
|
|
||||||
|
|
||||||
p = cpydig2(tms.tm_mday, p);
|
|
||||||
*p++ = '/';
|
|
||||||
p = std::ranges::copy(MONTH[tms.tm_mon], p).out;
|
|
||||||
*p++ = '/';
|
|
||||||
p = cpydig4(tms.tm_year + 1900, p);
|
|
||||||
*p++ = ':';
|
|
||||||
p = cpydig2(tms.tm_hour, p);
|
|
||||||
*p++ = ':';
|
|
||||||
p = cpydig2(tms.tm_min, p);
|
|
||||||
*p++ = ':';
|
|
||||||
p = cpydig2(tms.tm_sec, p);
|
|
||||||
*p++ = ' ';
|
|
||||||
|
|
||||||
#ifdef HAVE_STRUCT_TM_TM_GMTOFF
|
|
||||||
auto gmtoff = tms.tm_gmtoff;
|
|
||||||
#else // !HAVE_STRUCT_TM_TM_GMTOFF
|
|
||||||
auto gmtoff = nghttp2_timegm(&tms) - t;
|
|
||||||
#endif // !HAVE_STRUCT_TM_TM_GMTOFF
|
|
||||||
if (gmtoff >= 0) {
|
|
||||||
*p++ = '+';
|
|
||||||
} else {
|
|
||||||
*p++ = '-';
|
|
||||||
gmtoff = -gmtoff;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = cpydig2(gmtoff / 3600, p);
|
|
||||||
p = cpydig2((gmtoff % 3600) / 60, p);
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string format_iso8601(const std::chrono::system_clock::time_point &tp) {
|
std::string format_iso8601(const std::chrono::system_clock::time_point &tp) {
|
||||||
// 2014-11-15T12:58:24.741Z
|
// 2014-11-15T12:58:24.741Z
|
||||||
// 2014-11-15T12:58:24.741+09:00
|
// 2014-11-15T12:58:24.741+09:00
|
||||||
@@ -411,6 +364,56 @@ StringRef format_iso8601_basic(char *out,
|
|||||||
|
|
||||||
return {out, p};
|
return {out, p};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringRef format_common_log(char *out,
|
||||||
|
const std::chrono::system_clock::time_point &tp) {
|
||||||
|
return format_common_log(out, tp, get_current_time_zone());
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRef format_common_log(char *out,
|
||||||
|
const std::chrono::system_clock::time_point &tp,
|
||||||
|
const std::chrono::time_zone *tz) {
|
||||||
|
auto t = std::chrono::floor<std::chrono::milliseconds>(tp);
|
||||||
|
auto zt = std::chrono::zoned_time{tz, t};
|
||||||
|
auto lt = zt.get_local_time();
|
||||||
|
auto days = std::chrono::floor<std::chrono::days>(lt);
|
||||||
|
auto ymd = std::chrono::year_month_day{days};
|
||||||
|
|
||||||
|
auto p = out;
|
||||||
|
|
||||||
|
p = cpydig2(static_cast<uint32_t>(ymd.day()), p);
|
||||||
|
*p++ = '/';
|
||||||
|
p = std::ranges::copy(MONTH[static_cast<uint32_t>(ymd.month()) - 1], p).out;
|
||||||
|
*p++ = '/';
|
||||||
|
p = cpydig4(static_cast<int>(ymd.year()), p);
|
||||||
|
*p++ = ':';
|
||||||
|
|
||||||
|
auto hms = std::chrono::hh_mm_ss{lt - days};
|
||||||
|
|
||||||
|
p = cpydig2(hms.hours().count(), p);
|
||||||
|
*p++ = ':';
|
||||||
|
p = cpydig2(hms.minutes().count(), p);
|
||||||
|
*p++ = ':';
|
||||||
|
p = cpydig2(hms.seconds().count(), p);
|
||||||
|
*p++ = ' ';
|
||||||
|
|
||||||
|
auto sys_info = zt.get_info();
|
||||||
|
auto gmtoff =
|
||||||
|
std::chrono::floor<std::chrono::minutes>(sys_info.offset).count();
|
||||||
|
if (gmtoff >= 0) {
|
||||||
|
*p++ = '+';
|
||||||
|
} else {
|
||||||
|
*p++ = '-';
|
||||||
|
gmtoff = -gmtoff;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = cpydig2(gmtoff / 60, p);
|
||||||
|
p = cpydig2(gmtoff % 60, p);
|
||||||
|
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
return {out, p};
|
||||||
|
}
|
||||||
#else // !defined(HAVE_STD_CHRONO_TIME_ZONE)
|
#else // !defined(HAVE_STD_CHRONO_TIME_ZONE)
|
||||||
namespace {
|
namespace {
|
||||||
char *iso8601_date(char *out, const std::chrono::system_clock::time_point &tp) {
|
char *iso8601_date(char *out, const std::chrono::system_clock::time_point &tp) {
|
||||||
@@ -522,6 +525,58 @@ format_iso8601_basic(char *out,
|
|||||||
*p = '\0';
|
*p = '\0';
|
||||||
return {out, p};
|
return {out, p};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
char *common_log_date(char *out,
|
||||||
|
const std::chrono::system_clock::time_point &tp) {
|
||||||
|
time_t t =
|
||||||
|
std::chrono::floor<std::chrono::seconds>(tp.time_since_epoch()).count();
|
||||||
|
struct tm tms;
|
||||||
|
|
||||||
|
if (localtime_r(&t, &tms) == nullptr) {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto p = out;
|
||||||
|
|
||||||
|
p = cpydig2(tms.tm_mday, p);
|
||||||
|
*p++ = '/';
|
||||||
|
p = std::ranges::copy(MONTH[tms.tm_mon], p).out;
|
||||||
|
*p++ = '/';
|
||||||
|
p = cpydig4(tms.tm_year + 1900, p);
|
||||||
|
*p++ = ':';
|
||||||
|
p = cpydig2(tms.tm_hour, p);
|
||||||
|
*p++ = ':';
|
||||||
|
p = cpydig2(tms.tm_min, p);
|
||||||
|
*p++ = ':';
|
||||||
|
p = cpydig2(tms.tm_sec, p);
|
||||||
|
*p++ = ' ';
|
||||||
|
|
||||||
|
# ifdef HAVE_STRUCT_TM_TM_GMTOFF
|
||||||
|
auto gmtoff = tms.tm_gmtoff;
|
||||||
|
# else // !HAVE_STRUCT_TM_TM_GMTOFF
|
||||||
|
auto gmtoff = nghttp2_timegm(&tms) - t;
|
||||||
|
# endif // !HAVE_STRUCT_TM_TM_GMTOFF
|
||||||
|
if (gmtoff >= 0) {
|
||||||
|
*p++ = '+';
|
||||||
|
} else {
|
||||||
|
*p++ = '-';
|
||||||
|
gmtoff = -gmtoff;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = cpydig2(gmtoff / 3600, p);
|
||||||
|
p = cpydig2((gmtoff % 3600) / 60, p);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
StringRef format_common_log(char *out,
|
||||||
|
const std::chrono::system_clock::time_point &tp) {
|
||||||
|
auto p = common_log_date(out, tp);
|
||||||
|
*p = '\0';
|
||||||
|
return {out, p};
|
||||||
|
}
|
||||||
#endif // !defined(HAVE_STD_CHRONO_TIME_ZONE)
|
#endif // !defined(HAVE_STD_CHRONO_TIME_ZONE)
|
||||||
|
|
||||||
time_t parse_http_date(const StringRef &s) {
|
time_t parse_http_date(const StringRef &s) {
|
||||||
|
|||||||
31
src/util.h
31
src/util.h
@@ -499,14 +499,6 @@ std::string http_date(time_t t);
|
|||||||
// long. This function returns the one beyond the last position.
|
// long. This function returns the one beyond the last position.
|
||||||
char *http_date(char *res, time_t t);
|
char *http_date(char *res, time_t t);
|
||||||
|
|
||||||
// Returns given time |t| from epoch in Common Log format (e.g.,
|
|
||||||
// 03/Jul/2014:00:19:38 +0900)
|
|
||||||
std::string common_log_date(time_t t);
|
|
||||||
// Writes given time |t| from epoch in Common Log format into the
|
|
||||||
// buffer pointed by |res|. The buffer must be at least 26 bytes
|
|
||||||
// long. This function returns the one beyond the last position.
|
|
||||||
char *common_log_date(char *res, time_t t);
|
|
||||||
|
|
||||||
time_t parse_http_date(const StringRef &s);
|
time_t parse_http_date(const StringRef &s);
|
||||||
|
|
||||||
// Parses time formatted as "MMM DD HH:MM:SS YYYY [GMT]" (e.g., Feb 3
|
// Parses time formatted as "MMM DD HH:MM:SS YYYY [GMT]" (e.g., Feb 3
|
||||||
@@ -917,17 +909,18 @@ std::vector<StringRef> split_str(const StringRef &s, char delim, size_t n);
|
|||||||
|
|
||||||
// Writes given time |tp| in Common Log format (e.g.,
|
// Writes given time |tp| in Common Log format (e.g.,
|
||||||
// 03/Jul/2014:00:19:38 +0900) in buffer pointed by |out|. The buffer
|
// 03/Jul/2014:00:19:38 +0900) in buffer pointed by |out|. The buffer
|
||||||
// must be at least 27 bytes, including terminal NULL byte. Expected
|
// must be at least 27 bytes, including terminal NULL byte. This
|
||||||
// type of |tp| is std::chrono::time_point. This function returns
|
// function returns StringRef wrapping the buffer pointed by |out|,
|
||||||
// StringRef wrapping the buffer pointed by |out|, and this string is
|
// and this string is terminated by NULL.
|
||||||
// terminated by NULL.
|
StringRef format_common_log(char *out,
|
||||||
template <typename T> StringRef format_common_log(char *out, const T &tp) {
|
const std::chrono::system_clock::time_point &tp);
|
||||||
auto t =
|
|
||||||
std::chrono::duration_cast<std::chrono::seconds>(tp.time_since_epoch());
|
#ifdef HAVE_STD_CHRONO_TIME_ZONE
|
||||||
auto p = common_log_date(out, t.count());
|
// Works like above but with a given time zone.
|
||||||
*p = '\0';
|
StringRef format_common_log(char *out,
|
||||||
return StringRef{out, p};
|
const std::chrono::system_clock::time_point &tp,
|
||||||
}
|
const std::chrono::time_zone *tz);
|
||||||
|
#endif // defined(HAVE_STD_CHRONO_TIME_ZONE)
|
||||||
|
|
||||||
// Returns given time |tp| in ISO 8601 format (e.g.,
|
// Returns given time |tp| in ISO 8601 format (e.g.,
|
||||||
// 2014-11-15T12:58:24.741Z or 2014-11-15T12:58:24.741+09:00).
|
// 2014-11-15T12:58:24.741Z or 2014-11-15T12:58:24.741+09:00).
|
||||||
|
|||||||
@@ -655,70 +655,78 @@ void test_util_parse_http_date(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void test_util_localtime_date(void) {
|
void test_util_localtime_date(void) {
|
||||||
auto tz = getenv("TZ");
|
std::array<char, 30> buf;
|
||||||
if (tz) {
|
|
||||||
tz = strdup(tz);
|
|
||||||
}
|
|
||||||
#ifdef __linux__
|
|
||||||
setenv("TZ", "NZST-12:00:00:00", 1);
|
|
||||||
#else // !__linux__
|
|
||||||
setenv("TZ", ":Pacific/Auckland", 1);
|
|
||||||
#endif // !__linux__
|
|
||||||
tzset();
|
|
||||||
|
|
||||||
assert_stdstring_equal("02/Oct/2001:00:34:56 +1200",
|
|
||||||
util::common_log_date(1001939696));
|
|
||||||
|
|
||||||
std::array<char, 27> common_buf;
|
|
||||||
|
|
||||||
assert_stdsv_equal("02/Oct/2001:00:34:56 +1200"sv,
|
|
||||||
util::format_common_log(
|
|
||||||
common_buf.data(), std::chrono::system_clock::time_point(
|
|
||||||
std::chrono::seconds(1001939696))));
|
|
||||||
|
|
||||||
std::array<char, 30> iso8601_buf;
|
|
||||||
|
|
||||||
#ifdef HAVE_STD_CHRONO_TIME_ZONE
|
#ifdef HAVE_STD_CHRONO_TIME_ZONE
|
||||||
assert_stdsv_equal(
|
assert_stdsv_equal(
|
||||||
"2001-10-02T00:34:56.123+12:00"sv,
|
"2001-10-02T00:34:56.123+12:00"sv,
|
||||||
util::format_iso8601(iso8601_buf.data(),
|
util::format_iso8601(buf.data(),
|
||||||
std::chrono::system_clock::time_point(
|
std::chrono::system_clock::time_point(
|
||||||
std::chrono::milliseconds(1001939696123LL)),
|
std::chrono::milliseconds(1001939696123LL)),
|
||||||
std::chrono::locate_zone("Pacific/Auckland"sv)));
|
std::chrono::locate_zone("Pacific/Auckland"sv)));
|
||||||
|
|
||||||
assert_stdsv_equal(
|
assert_stdsv_equal(
|
||||||
"20011002T003456.123+1200"sv,
|
"20011002T003456.123+1200"sv,
|
||||||
util::format_iso8601_basic(iso8601_buf.data(),
|
util::format_iso8601_basic(buf.data(),
|
||||||
std::chrono::system_clock::time_point(
|
std::chrono::system_clock::time_point(
|
||||||
std::chrono::milliseconds(1001939696123LL)),
|
std::chrono::milliseconds(1001939696123LL)),
|
||||||
std::chrono::locate_zone("Pacific/Auckland"sv)));
|
std::chrono::locate_zone("Pacific/Auckland"sv)));
|
||||||
|
|
||||||
|
assert_stdsv_equal(
|
||||||
|
"02/Oct/2001:00:34:56 +1200"sv,
|
||||||
|
util::format_common_log(
|
||||||
|
buf.data(),
|
||||||
|
std::chrono::system_clock::time_point(std::chrono::seconds(1001939696)),
|
||||||
|
std::chrono::locate_zone("Pacific/Auckland"sv)));
|
||||||
|
|
||||||
assert_stdsv_equal(
|
assert_stdsv_equal(
|
||||||
"2001-10-01T12:34:56.123Z"sv,
|
"2001-10-01T12:34:56.123Z"sv,
|
||||||
util::format_iso8601(iso8601_buf.data(),
|
util::format_iso8601(buf.data(),
|
||||||
std::chrono::system_clock::time_point(
|
std::chrono::system_clock::time_point(
|
||||||
std::chrono::milliseconds(1001939696123LL)),
|
std::chrono::milliseconds(1001939696123LL)),
|
||||||
std::chrono::locate_zone("GMT"sv)));
|
std::chrono::locate_zone("GMT"sv)));
|
||||||
|
|
||||||
assert_stdsv_equal(
|
assert_stdsv_equal(
|
||||||
"20011001T123456.123Z"sv,
|
"20011001T123456.123Z"sv,
|
||||||
util::format_iso8601_basic(iso8601_buf.data(),
|
util::format_iso8601_basic(buf.data(),
|
||||||
std::chrono::system_clock::time_point(
|
std::chrono::system_clock::time_point(
|
||||||
std::chrono::milliseconds(1001939696123LL)),
|
std::chrono::milliseconds(1001939696123LL)),
|
||||||
std::chrono::locate_zone("GMT"sv)));
|
std::chrono::locate_zone("GMT"sv)));
|
||||||
#else // !defined(HAVE_STD_CHRONO_TIME_ZONE)
|
|
||||||
|
assert_stdsv_equal(
|
||||||
|
"01/Oct/2001:12:34:56 +0000"sv,
|
||||||
|
util::format_common_log(
|
||||||
|
buf.data(),
|
||||||
|
std::chrono::system_clock::time_point(std::chrono::seconds(1001939696)),
|
||||||
|
std::chrono::locate_zone("GMT"sv)));
|
||||||
|
#else // !defined(HAVE_STD_CHRONO_TIME_ZONE)
|
||||||
|
auto tz = getenv("TZ");
|
||||||
|
if (tz) {
|
||||||
|
tz = strdup(tz);
|
||||||
|
}
|
||||||
|
# ifdef __linux__
|
||||||
|
setenv("TZ", "NZST-12:00:00:00", 1);
|
||||||
|
# else // !__linux__
|
||||||
|
setenv("TZ", ":Pacific/Auckland", 1);
|
||||||
|
# endif // !__linux__
|
||||||
|
tzset();
|
||||||
|
|
||||||
assert_stdsv_equal(
|
assert_stdsv_equal(
|
||||||
"2001-10-02T00:34:56.123+12:00"sv,
|
"2001-10-02T00:34:56.123+12:00"sv,
|
||||||
util::format_iso8601(iso8601_buf.data(),
|
util::format_iso8601(buf.data(),
|
||||||
std::chrono::system_clock::time_point(
|
std::chrono::system_clock::time_point(
|
||||||
std::chrono::milliseconds(1001939696123LL))));
|
std::chrono::milliseconds(1001939696123LL))));
|
||||||
|
|
||||||
assert_stdsv_equal(
|
assert_stdsv_equal(
|
||||||
"20011002T003456.123+1200"sv,
|
"20011002T003456.123+1200"sv,
|
||||||
util::format_iso8601_basic(iso8601_buf.data(),
|
util::format_iso8601_basic(buf.data(),
|
||||||
std::chrono::system_clock::time_point(
|
std::chrono::system_clock::time_point(
|
||||||
std::chrono::milliseconds(1001939696123LL))));
|
std::chrono::milliseconds(1001939696123LL))));
|
||||||
#endif // !defined(HAVE_STD_CHRONO_TIME_ZONE)
|
|
||||||
|
assert_stdsv_equal(
|
||||||
|
"02/Oct/2001:00:34:56 +1200"sv,
|
||||||
|
util::format_common_log(buf.data(), std::chrono::system_clock::time_point(
|
||||||
|
std::chrono::seconds(1001939696))));
|
||||||
|
|
||||||
if (tz) {
|
if (tz) {
|
||||||
setenv("TZ", tz, 1);
|
setenv("TZ", tz, 1);
|
||||||
@@ -727,6 +735,7 @@ void test_util_localtime_date(void) {
|
|||||||
unsetenv("TZ");
|
unsetenv("TZ");
|
||||||
}
|
}
|
||||||
tzset();
|
tzset();
|
||||||
|
#endif // !defined(HAVE_STD_CHRONO_TIME_ZONE)
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_util_get_uint64(void) {
|
void test_util_get_uint64(void) {
|
||||||
|
|||||||
Reference in New Issue
Block a user