Implement faster formatting for format_iso8601 and format_common_log
This commit is contained in:
parent
df401f57a2
commit
de2a855572
96
src/util.cc
96
src/util.cc
|
@ -167,7 +167,7 @@ std::string quote_string(const std::string& target)
|
|||
|
||||
namespace {
|
||||
template<typename Iterator>
|
||||
Iterator cpydig(Iterator d, int n, size_t len)
|
||||
Iterator cpydig(Iterator d, uint32_t n, size_t len)
|
||||
{
|
||||
auto p = d + len - 1;
|
||||
|
||||
|
@ -223,6 +223,100 @@ std::string http_date(time_t t)
|
|||
return res;
|
||||
}
|
||||
|
||||
std::string common_log_date(time_t t)
|
||||
{
|
||||
struct tm tms;
|
||||
|
||||
if(localtime_r(&t, &tms) == nullptr) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Format data like this:
|
||||
// 03/Jul/2014:00:19:38 +0900
|
||||
std::string res;
|
||||
res.resize(26);
|
||||
|
||||
auto p = std::begin(res);
|
||||
|
||||
p = cpydig(p, tms.tm_mday, 2);
|
||||
*p++ = '/';
|
||||
auto s = MONTH[tms.tm_mon];
|
||||
p = std::copy(s, s + 3, p);
|
||||
*p++ = '/';
|
||||
p = cpydig(p, tms.tm_year + 1900, 4);
|
||||
*p++ = ':';
|
||||
p = cpydig(p, tms.tm_hour, 2);
|
||||
*p++ = ':';
|
||||
p = cpydig(p, tms.tm_min, 2);
|
||||
*p++ = ':';
|
||||
p = cpydig(p, tms.tm_sec, 2);
|
||||
*p++ = ' ';
|
||||
|
||||
auto gmtoff = tms.tm_gmtoff;
|
||||
if(gmtoff >= 0) {
|
||||
*p++ = '+';
|
||||
} else {
|
||||
*p++ = '-';
|
||||
gmtoff = -gmtoff;
|
||||
}
|
||||
|
||||
p = cpydig(p, gmtoff / 3600, 2);
|
||||
p = cpydig(p, (gmtoff % 3600) / 60, 2);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string iso8601_date(int64_t ms)
|
||||
{
|
||||
time_t sec = ms / 1000;
|
||||
|
||||
tm tms;
|
||||
if(localtime_r(&sec, &tms) == nullptr) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Format data like this:
|
||||
// 2014-11-15T12:58:24.741Z
|
||||
// 2014-11-15T12:58:24.741+09:00
|
||||
std::string res;
|
||||
res.resize(29);
|
||||
|
||||
auto p = std::begin(res);
|
||||
|
||||
p = cpydig(p, tms.tm_year + 1900, 4);
|
||||
*p++ = '-';
|
||||
p = cpydig(p, tms.tm_mon + 1, 2);
|
||||
*p++ = '-';
|
||||
p = cpydig(p, tms.tm_mday, 2);
|
||||
*p++ = 'T';
|
||||
p = cpydig(p, tms.tm_hour, 2);
|
||||
*p++ = ':';
|
||||
p = cpydig(p, tms.tm_min, 2);
|
||||
*p++ = ':';
|
||||
p = cpydig(p, tms.tm_sec, 2);
|
||||
*p++ = '.';
|
||||
p = cpydig(p, ms % 1000, 3);
|
||||
|
||||
auto gmtoff = tms.tm_gmtoff;
|
||||
if(gmtoff == 0) {
|
||||
*p++ = 'Z';
|
||||
} else {
|
||||
if(gmtoff > 0) {
|
||||
*p++ = '+';
|
||||
} else {
|
||||
*p++ = '-';
|
||||
gmtoff = -gmtoff;
|
||||
}
|
||||
p = cpydig(p, gmtoff / 3600, 2);
|
||||
*p++ = ':';
|
||||
p = cpydig(p, (gmtoff % 3600) / 60, 2);
|
||||
}
|
||||
|
||||
res.resize(p - std::begin(res));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
time_t parse_http_date(const std::string& s)
|
||||
{
|
||||
tm tm;
|
||||
|
|
37
src/util.h
37
src/util.h
|
@ -212,6 +212,14 @@ std::string format_hex(const unsigned char *s, size_t len);
|
|||
|
||||
std::string http_date(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);
|
||||
|
||||
// Returns given millisecond |ms| from epoch in ISO 8601 format (e.g.,
|
||||
// 2014-11-15T12:58:24.741Z)
|
||||
std::string iso8601_date(int64_t ms);
|
||||
|
||||
time_t parse_http_date(const std::string& s);
|
||||
|
||||
template<typename InputIterator1, typename InputIterator2>
|
||||
|
@ -489,21 +497,11 @@ std::vector<unsigned char> get_default_alpn();
|
|||
template <typename T>
|
||||
std::string format_common_log(const T& tp)
|
||||
{
|
||||
auto t = std::chrono::duration_cast<std::chrono::milliseconds>
|
||||
auto t = std::chrono::duration_cast<std::chrono::seconds>
|
||||
(tp.time_since_epoch());
|
||||
time_t sec = t.count() / 1000;
|
||||
|
||||
tm tms;
|
||||
if(localtime_r(&sec, &tms) == nullptr) {
|
||||
return "";
|
||||
return common_log_date(t.count());
|
||||
}
|
||||
|
||||
char buf[32];
|
||||
|
||||
strftime(buf, sizeof(buf), "%d/%b/%Y:%T %z", &tms);
|
||||
|
||||
return buf;
|
||||
}
|
||||
// Returns given time |tp| in ISO 8601 format (e.g.,
|
||||
// 2014-11-15T12:58:24.741Z)
|
||||
// Expected type of |tp| is std::chrono::timepoint
|
||||
|
@ -512,20 +510,7 @@ std::string format_iso8601(const T& tp)
|
|||
{
|
||||
auto t = std::chrono::duration_cast<std::chrono::milliseconds>
|
||||
(tp.time_since_epoch());
|
||||
time_t sec = t.count() / 1000;
|
||||
|
||||
tm tms;
|
||||
if(gmtime_r(&sec, &tms) == nullptr) {
|
||||
return "";
|
||||
}
|
||||
|
||||
char buf[128];
|
||||
|
||||
auto nwrite = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tms);
|
||||
snprintf(&buf[nwrite], sizeof(buf) - nwrite, ".%03ldZ",
|
||||
static_cast<int>(t.count() % 1000));
|
||||
|
||||
return buf;
|
||||
return iso8601_date(t.count());
|
||||
}
|
||||
|
||||
// Return the system precision of the template parameter |Clock| as
|
||||
|
|
Loading…
Reference in New Issue