Commit 364b053e authored by Dennis Jenkins's avatar Dennis Jenkins

clang-format most header files.

parent 16fbe079
This diff is collapsed.
......@@ -6,59 +6,58 @@
#pragma once
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <iostream>
#include <cstring>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#define TRY(...) \
do { \
auto ret = __VA_ARGS__; \
if (ret < 0) { \
const char* str = #__VA_ARGS__; \
std::ostringstream oss; \
oss << str << ": "; \
if (errno == 0) { \
oss << gai_strerror(ret); \
} else { \
oss << strerror(errno); \
} \
oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \
throw std::runtime_error(oss.str()); \
} \
} while (0)
#define TRY_RET(...) \
[&]() { \
auto ret = __VA_ARGS__; \
if (ret < 0) { \
const char *str = #__VA_ARGS__; \
std::ostringstream oss; \
oss << str << ": " << strerror(errno); \
oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \
throw std::runtime_error(oss.str()); \
} \
return ret; \
}(); \
(void) 0
#define TRY(...) \
do { \
auto ret = __VA_ARGS__; \
if (ret < 0) { \
const char *str = #__VA_ARGS__; \
std::ostringstream oss; \
oss << str << ": "; \
if (errno == 0) { \
oss << gai_strerror(ret); \
} else { \
oss << strerror(errno); \
} \
oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \
throw std::runtime_error(oss.str()); \
} \
} while (0)
#define TRY_RET(...) \
[&]() { \
auto ret = __VA_ARGS__; \
if (ret < 0) { \
const char *str = #__VA_ARGS__; \
std::ostringstream oss; \
oss << str << ": " << strerror(errno); \
oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \
throw std::runtime_error(oss.str()); \
} \
return ret; \
}(); \
(void)0
struct PrintException {
void operator()(std::exception_ptr exc) const {
try {
std::rethrow_exception(exc);
} catch (const std::exception& e) {
std::cerr << "An exception occured: " << e.what() << std::endl;
}
void operator()(std::exception_ptr exc) const {
try {
std::rethrow_exception(exc);
} catch (const std::exception &e) {
std::cerr << "An exception occured: " << e.what() << std::endl;
}
}
};
#define unreachable() __builtin_unreachable()
// Until we require C++17 compiler with [[maybe_unused]]
#define UNUSED(x) (void)(x);
......@@ -5,22 +5,21 @@
#include <limits>
// Allow compile-time overload
namespace Pistache
{
namespace Const
{
static constexpr size_t MaxBacklog = 128;
static constexpr size_t MaxEvents = 1024;
static constexpr size_t MaxBuffer = 4096;
static constexpr size_t DefaultWorkers = 1;
namespace Pistache {
namespace Const {
static constexpr size_t MaxBacklog = 128;
static constexpr size_t MaxEvents = 1024;
static constexpr size_t MaxBuffer = 4096;
static constexpr size_t DefaultWorkers = 1;
static constexpr size_t DefaultTimerPoolSize = 128;
static constexpr size_t DefaultTimerPoolSize = 128;
// Defined from CMakeLists.txt in project root
static constexpr size_t DefaultMaxRequestSize = 4096;
static constexpr size_t DefaultMaxResponseSize = std::numeric_limits<uint32_t>::max();
static constexpr size_t ChunkSize = 1024;
// Defined from CMakeLists.txt in project root
static constexpr size_t DefaultMaxRequestSize = 4096;
static constexpr size_t DefaultMaxResponseSize =
std::numeric_limits<uint32_t>::max();
static constexpr size_t ChunkSize = 1024;
static constexpr uint16_t HTTP_STANDARD_PORT = 80;
static constexpr uint16_t HTTP_STANDARD_PORT = 80;
} // namespace Const
} // namespace Pistache
......@@ -7,132 +7,124 @@
#pragma once
#include <ctime>
#include <string>
#include <list>
#include <map>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <list>
#include <pistache/optional.h>
#include <pistache/http_defs.h>
#include <pistache/optional.h>
namespace Pistache {
namespace Http {
struct Cookie {
friend std::ostream& operator<<(std::ostream& os, const Cookie& cookie);
friend std::ostream &operator<<(std::ostream &os, const Cookie &cookie);
Cookie(std::string name, std::string value);
Cookie(std::string name, std::string value);
std::string name;
std::string value;
std::string name;
std::string value;
Optional<std::string> path;
Optional<std::string> domain;
Optional<FullDate> expires;
Optional<std::string> path;
Optional<std::string> domain;
Optional<FullDate> expires;
Optional<int> maxAge;
bool secure;
bool httpOnly;
Optional<int> maxAge;
bool secure;
bool httpOnly;
std::map<std::string, std::string> ext;
std::map<std::string, std::string> ext;
static Cookie fromRaw(const char* str, size_t len);
static Cookie fromString(const std::string& str);
static Cookie fromRaw(const char *str, size_t len);
static Cookie fromString(const std::string &str);
private:
void write(std::ostream& os) const;
void write(std::ostream &os) const;
};
std::ostream& operator<<(std::ostream& os, const Cookie& cookie);
std::ostream &operator<<(std::ostream &os, const Cookie &cookie);
class CookieJar {
public:
using HashMapCookies = std::unordered_map<std::string, Cookie>; // "value" -> Cookie
using Storage = std::unordered_map<std::string, HashMapCookies>; // "name" -> Hashmap("value" -> Cookie)
struct iterator : std::iterator<std::bidirectional_iterator_tag, Cookie> {
explicit iterator(const Storage::const_iterator& _iterator)
: iter_storage(_iterator)
, iter_cookie_values()
, iter_storage_end()
{ }
iterator(const Storage::const_iterator& _iterator, const Storage::const_iterator& end)
: iter_storage(_iterator)
, iter_cookie_values()
, iter_storage_end(end)
{
if(iter_storage != iter_storage_end) {
iter_cookie_values = iter_storage->second.begin();
}
}
Cookie operator*() const {
return iter_cookie_values->second; // return iter_storage->second;
}
const Cookie* operator->() const {
return &(iter_cookie_values->second);
}
iterator& operator++() {
++iter_cookie_values;
if(iter_cookie_values == iter_storage->second.end()) {
++iter_storage;
if(iter_storage != iter_storage_end)
iter_cookie_values = iter_storage->second.begin();
}
return *this;
}
iterator operator++(int) {
iterator ret(iter_storage,iter_storage_end);
++iter_cookie_values;
if(iter_cookie_values == iter_storage->second.end()) {
++iter_storage;
if(iter_storage != iter_storage_end) // this check is important
iter_cookie_values = iter_storage->second.begin();
}
return ret;
}
bool operator !=(iterator other) const {
return iter_storage != other.iter_storage;
}
bool operator==(iterator other) const {
return iter_storage == other.iter_storage;
}
private:
Storage::const_iterator iter_storage;
HashMapCookies::const_iterator iter_cookie_values;
Storage::const_iterator iter_storage_end; // we need to know where main hashmap ends.
};
CookieJar();
void add(const Cookie& cookie);
void removeAllCookies();
void addFromRaw(const char *str, size_t len);
Cookie get(const std::string& name) const;
bool has(const std::string& name) const;
iterator begin() const {
return iterator(cookies.begin(), cookies.end());
using HashMapCookies =
std::unordered_map<std::string, Cookie>; // "value" -> Cookie
using Storage = std::unordered_map<
std::string, HashMapCookies>; // "name" -> Hashmap("value" -> Cookie)
struct iterator : std::iterator<std::bidirectional_iterator_tag, Cookie> {
explicit iterator(const Storage::const_iterator &_iterator)
: iter_storage(_iterator), iter_cookie_values(), iter_storage_end() {}
iterator(const Storage::const_iterator &_iterator,
const Storage::const_iterator &end)
: iter_storage(_iterator), iter_cookie_values(), iter_storage_end(end) {
if (iter_storage != iter_storage_end) {
iter_cookie_values = iter_storage->second.begin();
}
}
iterator end() const {
return iterator(cookies.end());
Cookie operator*() const {
return iter_cookie_values->second; // return iter_storage->second;
}
const Cookie *operator->() const { return &(iter_cookie_values->second); }
iterator &operator++() {
++iter_cookie_values;
if (iter_cookie_values == iter_storage->second.end()) {
++iter_storage;
if (iter_storage != iter_storage_end)
iter_cookie_values = iter_storage->second.begin();
}
return *this;
}
iterator operator++(int) {
iterator ret(iter_storage, iter_storage_end);
++iter_cookie_values;
if (iter_cookie_values == iter_storage->second.end()) {
++iter_storage;
if (iter_storage != iter_storage_end) // this check is important
iter_cookie_values = iter_storage->second.begin();
}
return ret;
}
bool operator!=(iterator other) const {
return iter_storage != other.iter_storage;
}
bool operator==(iterator other) const {
return iter_storage == other.iter_storage;
}
private:
Storage::const_iterator iter_storage;
HashMapCookies::const_iterator iter_cookie_values;
Storage::const_iterator
iter_storage_end; // we need to know where main hashmap ends.
};
CookieJar();
void add(const Cookie &cookie);
void removeAllCookies();
void addFromRaw(const char *str, size_t len);
Cookie get(const std::string &name) const;
bool has(const std::string &name) const;
iterator begin() const { return iterator(cookies.begin(), cookies.end()); }
iterator end() const { return iterator(cookies.end()); }
private:
Storage cookies;
Storage cookies;
};
} // namespace Net
} // namespace Http
} // namespace Pistache
This diff is collapsed.
This diff is collapsed.
......@@ -6,166 +6,159 @@
#pragma once
#include <pistache/http.h>
#include <pistache/listener.h>
#include <pistache/net.h>
#include <pistache/http.h>
namespace Pistache {
namespace Http {
class Endpoint {
public:
struct Options {
friend class Endpoint;
Options& threads(int val);
Options& threadsName(const std::string& val);
Options& flags(Flags<Tcp::Options> flags);
Options& flags(Tcp::Options tcp_opts) {
flags(Flags<Tcp::Options>(tcp_opts));
return *this;
}
Options& backlog(int val);
Options& maxRequestSize(size_t val);
Options& maxResponseSize(size_t val);
[[deprecated("Replaced by maxRequestSize(val)")]]
Options& maxPayload(size_t val);
private:
int threads_;
std::string threadsName_;
Flags<Tcp::Options> flags_;
int backlog_;
size_t maxRequestSize_;
size_t maxResponseSize_;
Options();
};
Endpoint();
explicit Endpoint(const Address& addr);
template<typename... Args>
void initArgs(Args&& ...args) {
listener.init(std::forward<Args>(args)...);
}
void init(const Options& options = Options());
void setHandler(const std::shared_ptr<Handler>& handler);
void bind();
void bind(const Address& addr);
void serve();
void serveThreaded();
void shutdown();
/*!
* \brief Use SSL on this endpoint
*
* \param[in] cert Server certificate path
* \param[in] key Server key path
* \param[in] use_compression Wether or not use compression on the encryption
*
* Setup the SSL configuration for an endpoint. In order to do that, this
* function will init OpenSSL constants and load *all* algorithms. It will
* then load the server certificate and key, in order to use it later.
* *If the private key does not match the certificate, an exception will
* be thrown*
*
* \note use_compression is false by default to mitigate BREACH[1] and
* CRIME[2] vulnerabilities
* \note This function will throw an exception if pistache has not been
* compiled with PISTACHE_USE_SSL
*
* [1] https://en.wikipedia.org/wiki/BREACH
* [2] https://en.wikipedia.org/wiki/CRIME
*/
void useSSL(std::string cert, std::string key, bool use_compression = false);
/*!
* \brief Use SSL certificate authentication on this endpoint
*
* \param[in] ca_file Certificate Authority file
* \param[in] ca_path Certificate Authority path
* \param[in] cb OpenSSL verify callback[1]
*
* Change the SSL configuration in order to only accept verified client
* certificates. The function 'useSSL' *should* be called before this
* function.
* Due to the way we actually doesn't expose any OpenSSL internal types, the
* callback function is Cpp generic. The 'real' callback will be:
*
* int callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
*
* It is up to the caller to cast the second argument to an appropriate
* pointer:
*
* int store_callback(int preverify_ok, void *ctx) {
* X509_STORE_CTX *x509_ctx = (X509_STORE_CTX *)ctx;
*
* [...]
*
* if (all_good)
* return 1;
* return 0;
* }
*
* [...]
*
* endpoint->useSSLAuth(ca_file, ca_path, &store_callback);
*
* See the documentation[1] for more information about this callback.
*
* \sa useSSL
* \note This function will throw an exception if pistache has not been
* compiled with PISTACHE_USE_SSL
*
* [1] https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_verify.html
*/
void useSSLAuth(std::string ca_file, std::string ca_path = "", int (*cb)(int, void *) = NULL);
bool isBound() const {
return listener.isBound();
}
Port getPort() const {
return listener.getPort();
struct Options {
friend class Endpoint;
Options &threads(int val);
Options &threadsName(const std::string &val);
Options &flags(Flags<Tcp::Options> flags);
Options &flags(Tcp::Options tcp_opts) {
flags(Flags<Tcp::Options>(tcp_opts));
return *this;
}
Async::Promise<Tcp::Listener::Load> requestLoad(const Tcp::Listener::Load& old);
static Options options();
Options &backlog(int val);
Options &maxRequestSize(size_t val);
Options &maxResponseSize(size_t val);
[[deprecated("Replaced by maxRequestSize(val)")]] Options &
maxPayload(size_t val);
private:
int threads_;
std::string threadsName_;
Flags<Tcp::Options> flags_;
int backlog_;
size_t maxRequestSize_;
size_t maxResponseSize_;
Options();
};
Endpoint();
explicit Endpoint(const Address &addr);
template <typename... Args> void initArgs(Args &&... args) {
listener.init(std::forward<Args>(args)...);
}
void init(const Options &options = Options());
void setHandler(const std::shared_ptr<Handler> &handler);
void bind();
void bind(const Address &addr);
void serve();
void serveThreaded();
void shutdown();
/*!
* \brief Use SSL on this endpoint
*
* \param[in] cert Server certificate path
* \param[in] key Server key path
* \param[in] use_compression Wether or not use compression on the encryption
*
* Setup the SSL configuration for an endpoint. In order to do that, this
* function will init OpenSSL constants and load *all* algorithms. It will
* then load the server certificate and key, in order to use it later.
* *If the private key does not match the certificate, an exception will
* be thrown*
*
* \note use_compression is false by default to mitigate BREACH[1] and
* CRIME[2] vulnerabilities
* \note This function will throw an exception if pistache has not been
* compiled with PISTACHE_USE_SSL
*
* [1] https://en.wikipedia.org/wiki/BREACH
* [2] https://en.wikipedia.org/wiki/CRIME
*/
void useSSL(std::string cert, std::string key, bool use_compression = false);
/*!
* \brief Use SSL certificate authentication on this endpoint
*
* \param[in] ca_file Certificate Authority file
* \param[in] ca_path Certificate Authority path
* \param[in] cb OpenSSL verify callback[1]
*
* Change the SSL configuration in order to only accept verified client
* certificates. The function 'useSSL' *should* be called before this
* function.
* Due to the way we actually doesn't expose any OpenSSL internal types, the
* callback function is Cpp generic. The 'real' callback will be:
*
* int callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
*
* It is up to the caller to cast the second argument to an appropriate
* pointer:
*
* int store_callback(int preverify_ok, void *ctx) {
* X509_STORE_CTX *x509_ctx = (X509_STORE_CTX *)ctx;
*
* [...]
*
* if (all_good)
* return 1;
* return 0;
* }
*
* [...]
*
* endpoint->useSSLAuth(ca_file, ca_path, &store_callback);
*
* See the documentation[1] for more information about this callback.
*
* \sa useSSL
* \note This function will throw an exception if pistache has not been
* compiled with PISTACHE_USE_SSL
*
* [1] https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_verify.html
*/
void useSSLAuth(std::string ca_file, std::string ca_path = "",
int (*cb)(int, void *) = NULL);
bool isBound() const { return listener.isBound(); }
Port getPort() const { return listener.getPort(); }
Async::Promise<Tcp::Listener::Load>
requestLoad(const Tcp::Listener::Load &old);
static Options options();
private:
template <typename Method> void serveImpl(Method method) {
#define CALL_MEMBER_FN(obj, pmf) ((obj).*(pmf))
if (!handler_)
throw std::runtime_error("Must call setHandler() prior to serve()");
template<typename Method>
void serveImpl(Method method)
{
#define CALL_MEMBER_FN(obj, pmf) ((obj).*(pmf))
if (!handler_)
throw std::runtime_error("Must call setHandler() prior to serve()");
listener.setHandler(handler_);
listener.bind();
listener.setHandler(handler_);
listener.bind();
CALL_MEMBER_FN(listener, method)();
CALL_MEMBER_FN(listener, method)();
#undef CALL_MEMBER_FN
}
}
std::shared_ptr<Handler> handler_;
Tcp::Listener listener;
std::shared_ptr<Handler> handler_;
Tcp::Listener listener;
};
template<typename Handler>
void listenAndServe(Address addr, const Endpoint::Options& options = Endpoint::options())
{
Endpoint endpoint(addr);
endpoint.init(options);
endpoint.setHandler(make_handler<Handler>());
endpoint.serve();
template <typename Handler>
void listenAndServe(Address addr,
const Endpoint::Options &options = Endpoint::options()) {
Endpoint endpoint(addr);
endpoint.init(options);
endpoint.setHandler(make_handler<Handler>());
endpoint.serve();
}
} // namespace Http
} // namespace Pistache
......@@ -5,19 +5,15 @@
namespace Pistache {
namespace Tcp {
class SocketError: public std::runtime_error
{
class SocketError : public std::runtime_error {
public:
explicit SocketError(const char* what_arg) : std::runtime_error(what_arg)
{ }
explicit SocketError(const char *what_arg) : std::runtime_error(what_arg) {}
};
class ServerError: public std::runtime_error
{
class ServerError : public std::runtime_error {
public:
explicit ServerError(const char* what_arg) : std::runtime_error(what_arg)
{ }
explicit ServerError(const char *what_arg) : std::runtime_error(what_arg) {}
};
} // Tcp
} // Pistache
\ No newline at end of file
} // namespace Tcp
} // namespace Pistache
\ No newline at end of file
/* flags.h
Mathieu Stefani, 18 August 2015
Make it easy to have bitwise operators for scoped or unscoped enumerations
*/
#pragma once
#include <type_traits>
#include <climits>
#include <iostream>
#include <type_traits>
namespace Pistache {
// Looks like gcc 4.6 does not implement std::underlying_type
namespace detail {
template<size_t N> struct TypeStorage;
template<> struct TypeStorage<sizeof(uint8_t)> {
typedef uint8_t Type;
};
template<> struct TypeStorage<sizeof(uint16_t)> {
typedef uint16_t Type;
};
template<> struct TypeStorage<sizeof(uint32_t)> {
typedef uint32_t Type;
};
template<> struct TypeStorage<sizeof(uint64_t)> {
typedef uint64_t Type;
};
template<typename T> struct UnderlyingType {
typedef typename TypeStorage<sizeof(T)>::Type Type;
};
template<typename Enum>
struct HasNone {
template<typename U>
static auto test(U *) -> decltype(U::None, std::true_type());
template<typename U>
static auto test(...) -> std::false_type;
static constexpr bool value =
std::is_same<decltype(test<Enum>(0)), std::true_type>::value;
};
}
template <size_t N> struct TypeStorage;
template <> struct TypeStorage<sizeof(uint8_t)> { typedef uint8_t Type; };
template <> struct TypeStorage<sizeof(uint16_t)> { typedef uint16_t Type; };
template <> struct TypeStorage<sizeof(uint32_t)> { typedef uint32_t Type; };
template <> struct TypeStorage<sizeof(uint64_t)> { typedef uint64_t Type; };
template <typename T> struct UnderlyingType {
typedef typename TypeStorage<sizeof(T)>::Type Type;
};
template <typename Enum> struct HasNone {
template <typename U>
static auto test(U *) -> decltype(U::None, std::true_type());
template <typename U> static auto test(...) -> std::false_type;
template<typename T>
class Flags {
static constexpr bool value =
std::is_same<decltype(test<Enum>(0)), std::true_type>::value;
};
} // namespace detail
template <typename T> class Flags {
public:
typedef typename detail::UnderlyingType<T>::Type Type;
static_assert(std::is_enum<T>::value, "Flags only works with enumerations");
static_assert(detail::HasNone<T>::value, "The enumartion needs a None value");
static_assert(static_cast<Type>(T::None) == 0, "None should be 0");
Flags() : val(T::None) {
}
explicit Flags(T _val) : val(_val) {
}
#define DEFINE_BITWISE_OP_CONST(Op) \
Flags<T> operator Op (T rhs) const { \
return Flags<T>( \
static_cast<T>(static_cast<Type>(val) Op static_cast<Type>(rhs)) \
); \
} \
\
Flags<T> operator Op (Flags<T> rhs) const { \
return Flags<T>( \
static_cast<T>(static_cast<Type>(val) Op static_cast<Type>(rhs.val)) \
); \
}
DEFINE_BITWISE_OP_CONST(|)
DEFINE_BITWISE_OP_CONST(&)
DEFINE_BITWISE_OP_CONST(^)
typedef typename detail::UnderlyingType<T>::Type Type;
static_assert(std::is_enum<T>::value, "Flags only works with enumerations");
static_assert(detail::HasNone<T>::value, "The enumartion needs a None value");
static_assert(static_cast<Type>(T::None) == 0, "None should be 0");
Flags() : val(T::None) {}
explicit Flags(T _val) : val(_val) {}
#define DEFINE_BITWISE_OP_CONST(Op) \
Flags<T> operator Op(T rhs) const { \
return Flags<T>( \
static_cast<T>(static_cast<Type>(val) Op static_cast<Type>(rhs))); \
} \
\
Flags<T> operator Op(Flags<T> rhs) const { \
return Flags<T>( \
static_cast<T>(static_cast<Type>(val) Op static_cast<Type>(rhs.val))); \
}
DEFINE_BITWISE_OP_CONST(|)
DEFINE_BITWISE_OP_CONST(&)
DEFINE_BITWISE_OP_CONST(^)
#undef DEFINE_BITWISE_OP_CONST
#define DEFINE_BITWISE_OP(Op) \
Flags<T>& operator Op##=(T rhs) { \
val = static_cast<T>( \
static_cast<Type>(val) Op static_cast<Type>(rhs) \
); \
return *this; \
} \
\
Flags<T>& operator Op##=(Flags<T> rhs) { \
val = static_cast<T>( \
static_cast<Type>(val) Op static_cast<Type>(rhs.val) \
); \
return *this; \
}
DEFINE_BITWISE_OP(|)
DEFINE_BITWISE_OP(&)
DEFINE_BITWISE_OP(^)
#define DEFINE_BITWISE_OP(Op) \
Flags<T> &operator Op##=(T rhs) { \
val = static_cast<T>(static_cast<Type>(val) Op static_cast<Type>(rhs)); \
return *this; \
} \
\
Flags<T> &operator Op##=(Flags<T> rhs) { \
val = \
static_cast<T>(static_cast<Type>(val) Op static_cast<Type>(rhs.val)); \
return *this; \
}
DEFINE_BITWISE_OP(|)
DEFINE_BITWISE_OP(&)
DEFINE_BITWISE_OP(^)
#undef DEFINE_BITWISE_OP
bool hasFlag(T flag) const {
return static_cast<Type>(val) & static_cast<Type>(flag);
}
bool hasFlag(T flag) const {
return static_cast<Type>(val) & static_cast<Type>(flag);
}
Flags<T>& setFlag(T flag) {
*this |= flag;
return *this;
}
Flags<T> &setFlag(T flag) {
*this |= flag;
return *this;
}
Flags<T>& toggleFlag(T flag) {
return *this ^= flag;
}
Flags<T> &toggleFlag(T flag) { return *this ^= flag; }
operator T() const {
return val;
}
operator T() const { return val; }
private:
T val;
T val;
};
} // namespace Pistache
#define DEFINE_BITWISE_OP(Op, T) \
inline T operator Op (T lhs, T rhs) { \
typedef Pistache::detail::UnderlyingType<T>::Type UnderlyingType; \
return static_cast<T>( \
static_cast<UnderlyingType>(lhs) Op static_cast<UnderlyingType>(rhs) \
); \
}
#define DEFINE_BITWISE_OP(Op, T) \
inline T operator Op(T lhs, T rhs) { \
typedef Pistache::detail::UnderlyingType<T>::Type UnderlyingType; \
return static_cast<T>(static_cast<UnderlyingType>(lhs) \
Op static_cast<UnderlyingType>(rhs)); \
}
#define DECLARE_FLAGS_OPERATORS(T) \
DEFINE_BITWISE_OP(&, T) \
DEFINE_BITWISE_OP(|, T)
#define DECLARE_FLAGS_OPERATORS(T) \
DEFINE_BITWISE_OP(&, T) \
DEFINE_BITWISE_OP(|, T)
template<typename T>
std::ostream& operator<<(std::ostream& os, Pistache::Flags<T> flags) {
typedef typename Pistache::detail::UnderlyingType<T>::Type UnderlyingType;
template <typename T>
std::ostream &operator<<(std::ostream &os, Pistache::Flags<T> flags) {
typedef typename Pistache::detail::UnderlyingType<T>::Type UnderlyingType;
auto val = static_cast<UnderlyingType>(static_cast<T>(flags));
for (ssize_t i = (sizeof(UnderlyingType) * CHAR_BIT) - 1; i >= 0; --i) {
os << ((val >> i) & 0x1);
}
auto val = static_cast<UnderlyingType>(static_cast<T>(flags));
for (ssize_t i = (sizeof(UnderlyingType) * CHAR_BIT) - 1; i >= 0; --i) {
os << ((val >> i) & 0x1);
}
return os;
return os;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -8,41 +8,32 @@
namespace Pistache {
template<typename Map>
struct FlatMapIteratorAdapter {
typedef typename Map::key_type Key;
typedef typename Map::mapped_type Value;
typedef typename Map::const_iterator const_iterator;
template <typename Map> struct FlatMapIteratorAdapter {
typedef typename Map::key_type Key;
typedef typename Map::mapped_type Value;
typedef typename Map::const_iterator const_iterator;
explicit FlatMapIteratorAdapter(const_iterator _it)
: it(_it)
{ }
explicit FlatMapIteratorAdapter(const_iterator _it) : it(_it) {}
FlatMapIteratorAdapter& operator++() {
++it;
return *this;
}
FlatMapIteratorAdapter &operator++() {
++it;
return *this;
}
const Value& operator*() {
return it->second;
}
const Value &operator*() { return it->second; }
bool operator==(FlatMapIteratorAdapter other) {
return other.it == it;
}
bool operator==(FlatMapIteratorAdapter other) { return other.it == it; }
bool operator!=(FlatMapIteratorAdapter other) {
return !(*this == other);
}
bool operator!=(FlatMapIteratorAdapter other) { return !(*this == other); }
private:
const_iterator it;
const_iterator it;
};
template<typename Map>
template <typename Map>
FlatMapIteratorAdapter<Map>
makeFlatMapIterator(const Map&, typename Map::const_iterator it) {
return FlatMapIteratorAdapter<Map>(it);
makeFlatMapIterator(const Map &, typename Map::const_iterator it) {
return FlatMapIteratorAdapter<Map>(it);
}
} // namespace Pistache
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
/*
Mathieu Stefani, 28 janvier 2016
Simple Prototype design pattern implement
*/
#pragma once
#include <type_traits>
#include <memory>
#include <type_traits>
namespace Pistache {
/* In a sense, a Prototype is just a class that provides a clone() method */
template<typename Class>
struct Prototype {
virtual ~Prototype() {}
virtual std::shared_ptr<Class> clone() const = 0;
template <typename Class> struct Prototype {
virtual ~Prototype() {}
virtual std::shared_ptr<Class> clone() const = 0;
};
} // namespace Pistache
#define PROTOTYPE_OF(Base, Class) \
private: \
std::shared_ptr<Base> clone() const override { \
return std::make_shared<Class>(*this); \
} \
#define PROTOTYPE_OF(Base, Class) \
private: \
std::shared_ptr<Base> clone() const override { \
return std::make_shared<Class>(*this); \
} \
\
public:
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -4,4 +4,4 @@ namespace Pistache {
#define REQUIRES(condition) typename std::enable_if<(condition), int>::type = 0
}
\ No newline at end of file
} // namespace Pistache
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
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