Unverified Commit 7ab86e10 authored by Dennis Jenkins's avatar Dennis Jenkins Committed by GitHub

Merge pull request #132 from xoac/date_h

Change std::tm to time_point and add "date.h"
parents 223a44cd 72ab1fcd
......@@ -4,7 +4,14 @@ dist: trusty
script: mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make
compiler:
- clang
- gcc
- gcc-5
before_install:
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
- sudo apt-get update -qq
- sudo apt-get install -qq libyajl-dev libxml2-dev libxqilla-dev
- if [ "$CXX" = "clang++" ]; then sudo apt-get install -qq libstdc++-5-dev; fi
- if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-5; fi
- if [ "$CXX" = "g++" ]; then export CXX="g++-5" CC="gcc-5"; fi
branches:
only:
- master
......
This diff is collapsed.
......@@ -10,7 +10,6 @@
#include <ostream>
#include <stdexcept>
#include <chrono>
#include <ctime>
#include <functional>
namespace Pistache {
......@@ -176,7 +175,8 @@ private:
// 3.3.1 Full Date
class FullDate {
public:
FullDate();
using time_point = std::chrono::system_clock::time_point;
FullDate() { }
enum class Type {
RFC1123,
......@@ -184,18 +184,17 @@ public:
AscTime
};
FullDate(std::tm date)
FullDate(time_point date)
: date_(date)
{ }
std::tm date() const { return date_; }
time_point date() const { return date_; }
void write(std::ostream& os, Type type = Type::RFC1123) const;
static FullDate fromRaw(const char* str, size_t len);
static FullDate fromString(const std::string& str);
private:
std::tm date_;
time_point date_;
};
const char* methodString(Method method);
......
......@@ -326,7 +326,7 @@ public:
fullDate_(date)
{ }
void parseRaw(const char* str, size_t len);
void parse(const std::string &str);
void write(std::ostream& os) const;
FullDate fullDate() const { return fullDate_; }
......
......@@ -17,6 +17,7 @@ set_target_properties(pistache PROPERTIES
VERSION ${GENERIC_LIB_VERSION}
SOVERSION ${GENERIC_LIB_SOVERSION}
)
add_definitions(-DONLY_C_LOCALE=1)
target_include_directories(pistache PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
......
......@@ -36,7 +36,7 @@ namespace {
struct AttributeMatcher<Optional<std::string>> {
static void match(StreamCursor& cursor, Cookie* obj, Optional<std::string> Cookie::*attr) {
auto token = matchValue(cursor);
obj->*attr = Some(std::string(token.rawText(), token.size()));
obj->*attr = Some(token.text());
}
};
......@@ -73,7 +73,7 @@ namespace {
struct AttributeMatcher<Optional<FullDate>> {
static void match(StreamCursor& cursor, Cookie* obj, Optional<FullDate> Cookie::*attr) {
auto token = matchValue(cursor);
obj->*attr = Some(FullDate::fromRaw(token.rawText(), token.size()));
obj->*attr = Some(FullDate::fromString(token.text()));
}
};
......
......@@ -9,25 +9,35 @@
#include <pistache/http_defs.h>
#include <pistache/common.h>
#include <pistache/date.h>
namespace Pistache {
namespace Http {
namespace {
bool parseRFC1123Date(std::tm& tm, const char* str, size_t len) {
char *p = strptime(str, "%a, %d %b %Y %H:%M:%S %Z", &tm);
return p != NULL;
using time_point = FullDate::time_point;
bool parse_RFC_1123(const std::string& s, time_point &tp)
{
std::istringstream in{s};
in >> date::parse("%a, %d %b %Y %T %Z", tp);
return !in.fail();
}
bool parseRFC850Date(std::tm& tm, const char* str, size_t len) {
char *p = strptime(str, "%A, %d-%b-%y %H:%M:%S %Z", &tm);
return p != NULL;
bool parse_RFC_850(const std::string& s, time_point &tp)
{
std::istringstream in{s};
in >> date::parse("%a, %d-%b-%y %T %Z", tp);
return !in.fail();
}
bool parseAscTimeDate(std::tm& tm, const char* str, size_t len) {
char *p = strptime(str, "%a %b %d %H:%M:%S %Y", &tm);
return p != NULL;
bool parse_asctime(const std::string& s, time_point &tp)
{
std::istringstream in{s};
in >> date::parse("%a %b %d %T %Y", tp);
return !in.fail();
}
} // anonymous namespace
CacheDirective::CacheDirective(Directive directive)
......@@ -77,51 +87,35 @@ CacheDirective::init(Directive directive, std::chrono::seconds delta)
}
}
FullDate::FullDate() {
std::memset(&date_, 0, sizeof date_);
}
FullDate
FullDate::fromRaw(const char* str, size_t len)
{
// As per the RFC, implementation MUST support all three formats.
std::tm tm = {};
if (parseRFC1123Date(tm, str, len)) {
return FullDate(tm);
}
memset(&tm, 0, sizeof tm);
if (parseRFC850Date(tm, str, len)) {
return FullDate(tm);
}
memset(&tm, 0, sizeof tm);
if (parseAscTimeDate(tm, str, len)) {
return FullDate(tm);
}
throw std::runtime_error("Invalid Date format");
}
FullDate
FullDate::fromString(const std::string& str) {
return FullDate::fromRaw(str.c_str(), str.size());
FullDate::time_point tp;
if(parse_RFC_1123(str, tp))
return FullDate(tp);
else if(parse_RFC_850(str, tp))
return FullDate(tp);
else if(parse_asctime(str, tp))
return FullDate(tp);
throw std::runtime_error("Invalid Date format");
}
void
FullDate::write(std::ostream& os, Type type) const
{
char buff[100];
std::memset(buff, 0, sizeof buff);
switch (type) {
case Type::RFC1123:
//os << std::put_time(&date_, "%a, %d %b %Y %H:%M:%S %Z");
if (std::strftime(buff, sizeof buff, "%a, %d %b %Y %H:%M:%S %Z", &date_))
os << buff;
date::to_stream(os, "%a, %d %b %Y %T %Z", date_);
break;
case Type::RFC850:
date::to_stream(os, "%a, %d-%b-%y %T %Z", date_);
break;
case Type::AscTime:
date::to_stream(os, "%a %b %d %T %Y", date_);
break;
default:
std::runtime_error("Invalid use of FullDate::write");
}
}
......
......@@ -304,8 +304,8 @@ ContentLength::write(std::ostream& os) const {
}
void
Date::parseRaw(const char* str, size_t len) {
fullDate_ = FullDate::fromRaw(str, len);
Date::parse(const std::string &str) {
fullDate_ = FullDate::fromString(str);
}
void
......
#include "gtest/gtest.h"
#include <pistache/cookie.h>
#include <pistache/date.h>
using namespace Pistache;
using namespace Pistache::Http;
......@@ -46,12 +47,11 @@ TEST(cookie_test, attributes_test) {
ASSERT_EQ(c.value, "en-US");
auto expires = c.expires.getOrElse(FullDate());
auto date = expires.date();
ASSERT_EQ(date.tm_year, 121);
ASSERT_EQ(date.tm_mon, 5);
ASSERT_EQ(date.tm_mday, 9);
ASSERT_EQ(date.tm_hour, 10);
ASSERT_EQ(date.tm_min, 18);
ASSERT_EQ(date.tm_sec, 14);
using namespace std::chrono;
FullDate::time_point expected_time_point = date::sys_days(date::year{2021}/6/9)
+ hours(10) + minutes(18) + seconds(14);
ASSERT_EQ(date, expected_time_point);
});
parse("lang=en-US; Path=/; Domain=example.com;", [](const Cookie& c) {
......@@ -102,15 +102,10 @@ TEST(cookie_test, write_test) {
ASSERT_EQ(oss.str(), "lang=fr-FR; Path=/; Domain=example.com");
Cookie c2("lang", "en-US");
std::tm expires;
std::memset(&expires, 0, sizeof expires);
expires.tm_isdst = 1;
expires.tm_mon = 2;
expires.tm_year = 118;
expires.tm_mday = 16;
expires.tm_hour = 17;
expires.tm_min = 0;
expires.tm_sec = 0;
using namespace std::chrono;
FullDate::time_point expires = date::sys_days(date::year{118}/2/16) + hours(17);
c2.path = Some(std::string("/"));
c2.expires = Some(FullDate(expires));
......
#include "gtest/gtest.h"
#include <chrono>
#include <pistache/http_headers.h>
#include <pistache/date.h>
using namespace Pistache::Http;
......@@ -194,45 +196,30 @@ TEST(headers_test, connection) {
}
}
TEST(headers_test, date_test) {
/* RFC-1123 */
using namespace std::chrono;
FullDate::time_point expected_time_point = date::sys_days(date::year{1994}/11/6)
+ hours(8) + minutes(49) + seconds(37);
/* RFC-1123 */
Header::Date d1;
d1.parse("Sun, 06 Nov 1994 08:49:37 GMT");
auto fd1 = d1.fullDate();
auto dd1 = fd1.date();
ASSERT_EQ(dd1.tm_year, 94);
ASSERT_EQ(dd1.tm_mon, 10);
ASSERT_EQ(dd1.tm_mday, 6);
ASSERT_EQ(dd1.tm_hour, 8);
ASSERT_EQ(dd1.tm_min, 49);
ASSERT_EQ(dd1.tm_sec, 37);
auto dd1 = d1.fullDate().date();
ASSERT_EQ(expected_time_point, dd1);
/* RFC-850 */
Header::Date d2;
d2.parse("Sunday, 06-Nov-94 08:49:37 GMT");
auto fd2 = d2.fullDate();
auto dd2 = fd2.date();
ASSERT_EQ(dd2.tm_year, 94);
ASSERT_EQ(dd2.tm_mon, 10);
ASSERT_EQ(dd2.tm_mday, 6);
ASSERT_EQ(dd2.tm_hour, 8);
ASSERT_EQ(dd2.tm_min, 49);
ASSERT_EQ(dd2.tm_sec, 37);
auto dd2 = d2.fullDate().date();
ASSERT_EQ(dd2, expected_time_point);
/* ANSI C's asctime format */
Header::Date d3;
d3.parse("Sun Nov 6 08:49:37 1994");
auto fd3 = d3.fullDate();
auto dd3 = fd3.date();
ASSERT_EQ(dd3.tm_year, 94);
ASSERT_EQ(dd3.tm_mon, 10);
ASSERT_EQ(dd3.tm_mday, 6);
ASSERT_EQ(dd3.tm_hour, 8);
ASSERT_EQ(dd3.tm_min, 49);
ASSERT_EQ(dd3.tm_sec, 37);
auto dd3 = d3.fullDate().date();
ASSERT_EQ(dd3, expected_time_point);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment