Unverified Commit 5f911e35 authored by Dennis Jenkins's avatar Dennis Jenkins Committed by GitHub

Merge pull request #676 from dennisjenkins75/master

clang-format most header files.
parents 16fbe079 364b053e
This diff is collapsed.
...@@ -6,59 +6,58 @@ ...@@ -6,59 +6,58 @@
#pragma once #pragma once
#include <iostream>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <iostream>
#include <cstring> #include <cstring>
#include <netdb.h> #include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h>
#define TRY(...) \ #define TRY(...) \
do { \ do { \
auto ret = __VA_ARGS__; \ auto ret = __VA_ARGS__; \
if (ret < 0) { \ if (ret < 0) { \
const char* str = #__VA_ARGS__; \ const char *str = #__VA_ARGS__; \
std::ostringstream oss; \ std::ostringstream oss; \
oss << str << ": "; \ oss << str << ": "; \
if (errno == 0) { \ if (errno == 0) { \
oss << gai_strerror(ret); \ oss << gai_strerror(ret); \
} else { \ } else { \
oss << strerror(errno); \ oss << strerror(errno); \
} \ } \
oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \ oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \
throw std::runtime_error(oss.str()); \ throw std::runtime_error(oss.str()); \
} \ } \
} while (0) } while (0)
#define TRY_RET(...) \ #define TRY_RET(...) \
[&]() { \ [&]() { \
auto ret = __VA_ARGS__; \ auto ret = __VA_ARGS__; \
if (ret < 0) { \ if (ret < 0) { \
const char *str = #__VA_ARGS__; \ const char *str = #__VA_ARGS__; \
std::ostringstream oss; \ std::ostringstream oss; \
oss << str << ": " << strerror(errno); \ oss << str << ": " << strerror(errno); \
oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \ oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \
throw std::runtime_error(oss.str()); \ throw std::runtime_error(oss.str()); \
} \ } \
return ret; \ return ret; \
}(); \ }(); \
(void) 0 (void)0
struct PrintException { struct PrintException {
void operator()(std::exception_ptr exc) const { void operator()(std::exception_ptr exc) const {
try { try {
std::rethrow_exception(exc); std::rethrow_exception(exc);
} catch (const std::exception& e) { } catch (const std::exception &e) {
std::cerr << "An exception occured: " << e.what() << std::endl; std::cerr << "An exception occured: " << e.what() << std::endl;
}
} }
}
}; };
#define unreachable() __builtin_unreachable() #define unreachable() __builtin_unreachable()
// Until we require C++17 compiler with [[maybe_unused]] // Until we require C++17 compiler with [[maybe_unused]]
#define UNUSED(x) (void)(x); #define UNUSED(x) (void)(x);
...@@ -5,22 +5,21 @@ ...@@ -5,22 +5,21 @@
#include <limits> #include <limits>
// Allow compile-time overload // Allow compile-time overload
namespace Pistache namespace Pistache {
{ namespace Const {
namespace Const static constexpr size_t MaxBacklog = 128;
{ static constexpr size_t MaxEvents = 1024;
static constexpr size_t MaxBacklog = 128; static constexpr size_t MaxBuffer = 4096;
static constexpr size_t MaxEvents = 1024; static constexpr size_t DefaultWorkers = 1;
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 // Defined from CMakeLists.txt in project root
static constexpr size_t DefaultMaxRequestSize = 4096; static constexpr size_t DefaultMaxRequestSize = 4096;
static constexpr size_t DefaultMaxResponseSize = std::numeric_limits<uint32_t>::max(); static constexpr size_t DefaultMaxResponseSize =
static constexpr size_t ChunkSize = 1024; 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 Const
} // namespace Pistache } // namespace Pistache
...@@ -7,132 +7,124 @@ ...@@ -7,132 +7,124 @@
#pragma once #pragma once
#include <ctime> #include <ctime>
#include <string> #include <list>
#include <map> #include <map>
#include <string>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include <list>
#include <pistache/optional.h>
#include <pistache/http_defs.h> #include <pistache/http_defs.h>
#include <pistache/optional.h>
namespace Pistache { namespace Pistache {
namespace Http { namespace Http {
struct Cookie { 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 name;
std::string value; std::string value;
Optional<std::string> path; Optional<std::string> path;
Optional<std::string> domain; Optional<std::string> domain;
Optional<FullDate> expires; Optional<FullDate> expires;
Optional<int> maxAge; Optional<int> maxAge;
bool secure; bool secure;
bool httpOnly; 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 fromRaw(const char *str, size_t len);
static Cookie fromString(const std::string& str); static Cookie fromString(const std::string &str);
private: 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 { class CookieJar {
public: public:
using HashMapCookies = std::unordered_map<std::string, Cookie>; // "value" -> Cookie using HashMapCookies =
using Storage = std::unordered_map<std::string, HashMapCookies>; // "name" -> Hashmap("value" -> Cookie) std::unordered_map<std::string, Cookie>; // "value" -> Cookie
using Storage = std::unordered_map<
struct iterator : std::iterator<std::bidirectional_iterator_tag, Cookie> { std::string, HashMapCookies>; // "name" -> Hashmap("value" -> Cookie)
explicit iterator(const Storage::const_iterator& _iterator)
: iter_storage(_iterator) struct iterator : std::iterator<std::bidirectional_iterator_tag, Cookie> {
, iter_cookie_values() explicit iterator(const Storage::const_iterator &_iterator)
, iter_storage_end() : iter_storage(_iterator), iter_cookie_values(), iter_storage_end() {}
{ }
iterator(const Storage::const_iterator &_iterator,
iterator(const Storage::const_iterator& _iterator, const Storage::const_iterator& end) const Storage::const_iterator &end)
: iter_storage(_iterator) : iter_storage(_iterator), iter_cookie_values(), iter_storage_end(end) {
, iter_cookie_values() if (iter_storage != iter_storage_end) {
, iter_storage_end(end) iter_cookie_values = iter_storage->second.begin();
{ }
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());
} }
iterator end() const { Cookie operator*() const {
return iterator(cookies.end()); 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: private:
Storage cookies; Storage cookies;
}; };
} // namespace Net } // namespace Http
} // namespace Pistache } // namespace Pistache
This diff is collapsed.
This diff is collapsed.
...@@ -6,166 +6,159 @@ ...@@ -6,166 +6,159 @@
#pragma once #pragma once
#include <pistache/http.h>
#include <pistache/listener.h> #include <pistache/listener.h>
#include <pistache/net.h> #include <pistache/net.h>
#include <pistache/http.h>
namespace Pistache { namespace Pistache {
namespace Http { namespace Http {
class Endpoint { class Endpoint {
public: public:
struct Options { struct Options {
friend class Endpoint; friend class Endpoint;
Options& threads(int val); Options &threads(int val);
Options& threadsName(const std::string& val); Options &threadsName(const std::string &val);
Options& flags(Flags<Tcp::Options> flags); Options &flags(Flags<Tcp::Options> flags);
Options& flags(Tcp::Options tcp_opts) { Options &flags(Tcp::Options tcp_opts) {
flags(Flags<Tcp::Options>(tcp_opts)); flags(Flags<Tcp::Options>(tcp_opts));
return *this; 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();
} }
Options &backlog(int val);
Async::Promise<Tcp::Listener::Load> requestLoad(const Tcp::Listener::Load& old); Options &maxRequestSize(size_t val);
Options &maxResponseSize(size_t val);
static Options options();
[[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: 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> listener.setHandler(handler_);
void serveImpl(Method method) listener.bind();
{
#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();
CALL_MEMBER_FN(listener, method)(); CALL_MEMBER_FN(listener, method)();
#undef CALL_MEMBER_FN #undef CALL_MEMBER_FN
} }
std::shared_ptr<Handler> handler_; std::shared_ptr<Handler> handler_;
Tcp::Listener listener; Tcp::Listener listener;
}; };
template<typename Handler> template <typename Handler>
void listenAndServe(Address addr, const Endpoint::Options& options = Endpoint::options()) void listenAndServe(Address addr,
{ const Endpoint::Options &options = Endpoint::options()) {
Endpoint endpoint(addr); Endpoint endpoint(addr);
endpoint.init(options); endpoint.init(options);
endpoint.setHandler(make_handler<Handler>()); endpoint.setHandler(make_handler<Handler>());
endpoint.serve(); endpoint.serve();
} }
} // namespace Http } // namespace Http
} // namespace Pistache } // namespace Pistache
...@@ -5,19 +5,15 @@ ...@@ -5,19 +5,15 @@
namespace Pistache { namespace Pistache {
namespace Tcp { namespace Tcp {
class SocketError: public std::runtime_error class SocketError : public std::runtime_error {
{
public: 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: public:
explicit ServerError(const char* what_arg) : std::runtime_error(what_arg) explicit ServerError(const char *what_arg) : std::runtime_error(what_arg) {}
{ }
}; };
} // Tcp } // namespace Tcp
} // Pistache } // namespace Pistache
\ No newline at end of file \ No newline at end of file
/* flags.h /* flags.h
Mathieu Stefani, 18 August 2015 Mathieu Stefani, 18 August 2015
Make it easy to have bitwise operators for scoped or unscoped enumerations Make it easy to have bitwise operators for scoped or unscoped enumerations
*/ */
#pragma once #pragma once
#include <type_traits>
#include <climits> #include <climits>
#include <iostream> #include <iostream>
#include <type_traits>
namespace Pistache { namespace Pistache {
// Looks like gcc 4.6 does not implement std::underlying_type // Looks like gcc 4.6 does not implement std::underlying_type
namespace detail { namespace detail {
template<size_t N> struct TypeStorage; template <size_t N> struct TypeStorage;
template<> struct TypeStorage<sizeof(uint8_t)> { template <> struct TypeStorage<sizeof(uint8_t)> { typedef uint8_t Type; };
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(uint16_t)> { template <> struct TypeStorage<sizeof(uint64_t)> { typedef uint64_t Type; };
typedef uint16_t Type;
}; template <typename T> struct UnderlyingType {
template<> struct TypeStorage<sizeof(uint32_t)> { typedef typename TypeStorage<sizeof(T)>::Type Type;
typedef uint32_t Type; };
};
template<> struct TypeStorage<sizeof(uint64_t)> { template <typename Enum> struct HasNone {
typedef uint64_t Type; template <typename U>
}; static auto test(U *) -> decltype(U::None, std::true_type());
template<typename T> struct UnderlyingType { template <typename U> static auto test(...) -> std::false_type;
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<typename T> static constexpr bool value =
class Flags { std::is_same<decltype(test<Enum>(0)), std::true_type>::value;
};
} // namespace detail
template <typename T> class Flags {
public: public:
typedef typename detail::UnderlyingType<T>::Type Type; typedef typename detail::UnderlyingType<T>::Type Type;
static_assert(std::is_enum<T>::value, "Flags only works with enumerations"); 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(detail::HasNone<T>::value, "The enumartion needs a None value");
static_assert(static_cast<Type>(T::None) == 0, "None should be 0"); static_assert(static_cast<Type>(T::None) == 0, "None should be 0");
Flags() : val(T::None) { Flags() : val(T::None) {}
}
explicit Flags(T _val) : val(_val) {}
explicit Flags(T _val) : val(_val) {
} #define DEFINE_BITWISE_OP_CONST(Op) \
Flags<T> operator Op(T rhs) const { \
#define DEFINE_BITWISE_OP_CONST(Op) \ return Flags<T>( \
Flags<T> operator Op (T rhs) const { \ static_cast<T>(static_cast<Type>(val) Op static_cast<Type>(rhs))); \
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))); \
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(^)
DEFINE_BITWISE_OP_CONST(|)
DEFINE_BITWISE_OP_CONST(&)
DEFINE_BITWISE_OP_CONST(^)
#undef DEFINE_BITWISE_OP_CONST #undef DEFINE_BITWISE_OP_CONST
#define DEFINE_BITWISE_OP(Op) \ #define DEFINE_BITWISE_OP(Op) \
Flags<T>& operator Op##=(T rhs) { \ Flags<T> &operator Op##=(T rhs) { \
val = static_cast<T>( \ val = static_cast<T>(static_cast<Type>(val) Op static_cast<Type>(rhs)); \
static_cast<Type>(val) Op static_cast<Type>(rhs) \ return *this; \
); \ } \
return *this; \ \
} \ Flags<T> &operator Op##=(Flags<T> rhs) { \
\ val = \
Flags<T>& operator Op##=(Flags<T> rhs) { \ static_cast<T>(static_cast<Type>(val) Op static_cast<Type>(rhs.val)); \
val = static_cast<T>( \ return *this; \
static_cast<Type>(val) Op static_cast<Type>(rhs.val) \ }
); \
return *this; \ DEFINE_BITWISE_OP(|)
} DEFINE_BITWISE_OP(&)
DEFINE_BITWISE_OP(^)
DEFINE_BITWISE_OP(|)
DEFINE_BITWISE_OP(&)
DEFINE_BITWISE_OP(^)
#undef DEFINE_BITWISE_OP #undef DEFINE_BITWISE_OP
bool hasFlag(T flag) const { bool hasFlag(T flag) const {
return static_cast<Type>(val) & static_cast<Type>(flag); return static_cast<Type>(val) & static_cast<Type>(flag);
} }
Flags<T>& setFlag(T flag) { Flags<T> &setFlag(T flag) {
*this |= flag; *this |= flag;
return *this; return *this;
} }
Flags<T>& toggleFlag(T flag) { Flags<T> &toggleFlag(T flag) { return *this ^= flag; }
return *this ^= flag;
}
operator T() const { operator T() const { return val; }
return val;
}
private: private:
T val; T val;
}; };
} // namespace Pistache } // namespace Pistache
#define DEFINE_BITWISE_OP(Op, T) \ #define DEFINE_BITWISE_OP(Op, T) \
inline T operator Op (T lhs, T rhs) { \ inline T operator Op(T lhs, T rhs) { \
typedef Pistache::detail::UnderlyingType<T>::Type UnderlyingType; \ typedef Pistache::detail::UnderlyingType<T>::Type UnderlyingType; \
return static_cast<T>( \ return static_cast<T>(static_cast<UnderlyingType>(lhs) \
static_cast<UnderlyingType>(lhs) Op static_cast<UnderlyingType>(rhs) \ Op static_cast<UnderlyingType>(rhs)); \
); \ }
}
#define DECLARE_FLAGS_OPERATORS(T) \ #define DECLARE_FLAGS_OPERATORS(T) \
DEFINE_BITWISE_OP(&, T) \ DEFINE_BITWISE_OP(&, T) \
DEFINE_BITWISE_OP(|, T) DEFINE_BITWISE_OP(|, T)
template<typename T> template <typename T>
std::ostream& operator<<(std::ostream& os, Pistache::Flags<T> flags) { std::ostream &operator<<(std::ostream &os, Pistache::Flags<T> flags) {
typedef typename Pistache::detail::UnderlyingType<T>::Type UnderlyingType; typedef typename Pistache::detail::UnderlyingType<T>::Type UnderlyingType;
auto val = static_cast<UnderlyingType>(static_cast<T>(flags)); auto val = static_cast<UnderlyingType>(static_cast<T>(flags));
for (ssize_t i = (sizeof(UnderlyingType) * CHAR_BIT) - 1; i >= 0; --i) { for (ssize_t i = (sizeof(UnderlyingType) * CHAR_BIT) - 1; i >= 0; --i) {
os << ((val >> i) & 0x1); 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 @@ ...@@ -8,41 +8,32 @@
namespace Pistache { namespace Pistache {
template<typename Map> template <typename Map> struct FlatMapIteratorAdapter {
struct FlatMapIteratorAdapter { typedef typename Map::key_type Key;
typedef typename Map::key_type Key; typedef typename Map::mapped_type Value;
typedef typename Map::mapped_type Value; typedef typename Map::const_iterator const_iterator;
typedef typename Map::const_iterator const_iterator;
explicit FlatMapIteratorAdapter(const_iterator _it) explicit FlatMapIteratorAdapter(const_iterator _it) : it(_it) {}
: it(_it)
{ }
FlatMapIteratorAdapter& operator++() { FlatMapIteratorAdapter &operator++() {
++it; ++it;
return *this; return *this;
} }
const Value& operator*() { const Value &operator*() { return it->second; }
return it->second;
}
bool operator==(FlatMapIteratorAdapter other) { bool operator==(FlatMapIteratorAdapter other) { return other.it == it; }
return other.it == it;
}
bool operator!=(FlatMapIteratorAdapter other) { bool operator!=(FlatMapIteratorAdapter other) { return !(*this == other); }
return !(*this == other);
}
private: private:
const_iterator it; const_iterator it;
}; };
template<typename Map> template <typename Map>
FlatMapIteratorAdapter<Map> FlatMapIteratorAdapter<Map>
makeFlatMapIterator(const Map&, typename Map::const_iterator it) { makeFlatMapIterator(const Map &, typename Map::const_iterator it) {
return FlatMapIteratorAdapter<Map>(it); return FlatMapIteratorAdapter<Map>(it);
} }
} // namespace Pistache } // 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 Mathieu Stefani, 28 janvier 2016
Simple Prototype design pattern implement Simple Prototype design pattern implement
*/ */
#pragma once #pragma once
#include <type_traits>
#include <memory> #include <memory>
#include <type_traits>
namespace Pistache { namespace Pistache {
/* In a sense, a Prototype is just a class that provides a clone() method */ /* In a sense, a Prototype is just a class that provides a clone() method */
template<typename Class> template <typename Class> struct Prototype {
struct Prototype { virtual ~Prototype() {}
virtual ~Prototype() {} virtual std::shared_ptr<Class> clone() const = 0;
virtual std::shared_ptr<Class> clone() const = 0;
}; };
} // namespace Pistache } // namespace Pistache
#define PROTOTYPE_OF(Base, Class) \ #define PROTOTYPE_OF(Base, Class) \
private: \ private: \
std::shared_ptr<Base> clone() const override { \ std::shared_ptr<Base> clone() const override { \
return std::make_shared<Class>(*this); \ return std::make_shared<Class>(*this); \
} \ } \
\
public: 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 { ...@@ -4,4 +4,4 @@ namespace Pistache {
#define REQUIRES(condition) typename std::enable_if<(condition), int>::type = 0 #define REQUIRES(condition) typename std::enable_if<(condition), int>::type = 0
} } // namespace Pistache
\ No newline at end of file \ 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