File: //usr/include/hphp/util/afdt-util.h
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_AFDT_UTIL_H_
#define incl_HPHP_AFDT_UTIL_H_
#ifdef _MSC_VER
# error AFDT is not currently supported for MSVC!
#endif
#include <sys/socket.h>
#include <vector>
#include <string>
#include <stdexcept>
#include <cstring>
namespace HPHP {
namespace afdt {
///////////////////////////////////////////////////////////////////////////////
namespace detail {
typedef void (*SrFunc)(int afdt_fd, std::vector<iovec>& iov);
void sappend(int afdt_fd,
std::vector<iovec>& iov, const void* addr, size_t size);
void rappend(int afdt_fd,
std::vector<iovec>& iov, void* addr, size_t size);
template<class T>
typename std::enable_if<
std::is_fundamental<T>::value || std::is_pod<T>::value,
void
>::type sappend(int afdt_fd, std::vector<iovec>& iov, const T& elm) {
sappend(afdt_fd, iov, &elm, sizeof elm);
}
template<class T>
typename std::enable_if<
std::is_fundamental<T>::value || std::is_pod<T>::value,
void
>::type rappend(int afdt_fd, std::vector<iovec>& iov, T* elm) {
rappend(afdt_fd, iov, elm, sizeof *elm);
}
void send(int afdt_fd, std::vector<iovec>& iov);
template<class... Tail>
void send(int afdt_fd, std::vector<iovec>& iov,
const std::vector<std::string>& h, Tail&&... args);
template<class... Tail>
void send(int afdt_fd, std::vector<iovec>& iov,
const std::string& h, Tail&&... args);
template<class... Tail>
void send(int afdt_fd, std::vector<iovec>& iov,
const char* h, Tail&&... args);
template<class T, class... Tail>
typename std::enable_if<std::is_fundamental<T>::value, void>::type
send(int afdt_fd, std::vector<iovec>& iov,
const std::vector<T>& h, Tail&&... args);
template<class... Tail>
void send(int afdt_fd, std::vector<iovec>& iov,
const std::vector<std::string>& h, Tail&&... args);
template<class Head, class... Tail>
void send(int afdt_fd, std::vector<iovec>& iov,
const Head& h, Tail&&... args) {
sappend(afdt_fd, iov, h);
send(afdt_fd, iov, std::forward<Tail>(args)...);
}
template<class... Tail>
void send(int afdt_fd, std::vector<iovec>& iov,
const std::string& h, Tail&&... args) {
size_t s = h.size();
sappend(afdt_fd, iov, s);
sappend(afdt_fd, iov, &h[0], s);
send(afdt_fd, iov, std::forward<Tail>(args)...);
}
template<class... Tail>
void send(int afdt_fd, std::vector<iovec>& iov,
const char* h, Tail&&... args) {
size_t s = std::strlen(h);
sappend(afdt_fd, iov, s);
sappend(afdt_fd, iov, &h[0], s);
send(afdt_fd, iov, std::forward<Tail>(args)...);
}
template<class T, class... Tail>
typename std::enable_if<std::is_fundamental<T>::value, void>::type
send(int afdt_fd, std::vector<iovec>& iov,
const std::vector<T>& h, Tail&&... args) {
size_t s = h.size();
sappend(afdt_fd, iov, s);
sappend(afdt_fd, iov, &h[0], s * sizeof(T));
send(afdt_fd, iov, std::forward<Tail>(args)...);
}
template<class... Tail>
void send(int afdt_fd, std::vector<iovec>& iov,
const std::vector<std::string>& h, Tail&&... args) {
size_t s = h.size();
sappend(afdt_fd, iov, s);
std::vector<size_t> sizes;
sizes.reserve(s);
for (auto& e : h) {
auto strsz = e.size();
sizes.push_back(strsz);
sappend(afdt_fd, iov, sizes.back());
sappend(afdt_fd, iov, &e[0], strsz);
}
send(afdt_fd, iov, std::forward<Tail>(args)...);
}
void recv(int afdt_fd, std::vector<iovec>& iov);
template<class... Tail>
void recv(int afdt_fd, std::vector<iovec>& iov,
std::string& h, Tail&... args);
template<class T, class... Tail>
typename std::enable_if<std::is_fundamental<T>::value, void>::type
recv(int afdt_fd, std::vector<iovec>& iov,
std::vector<T>& h, Tail&... args);
template<class... Tail>
void recv(int afdt_fd, std::vector<iovec>& iov,
std::vector<std::string>& h, Tail&... args);
template<class Head, class... Tail>
void recv(int afdt_fd, std::vector<iovec>& iov,
Head& h, Tail&... args) {
rappend(afdt_fd, iov, &h);
recv(afdt_fd, iov, args...);
}
template<class... Tail>
void recv(int afdt_fd, std::vector<iovec>& iov,
std::string& h, Tail&... args) {
size_t sz;
rappend(afdt_fd, iov, &sz);
recv(afdt_fd, iov);
iov.clear();
h.resize(sz);
rappend(afdt_fd, iov, &h[0], sz);
recv(afdt_fd, iov, args...);
}
template<class T, class... Tail>
typename std::enable_if<std::is_fundamental<T>::value, void>::type
recv(int afdt_fd, std::vector<iovec>& iov,
std::vector<T>& h, Tail&... args) {
size_t sz;
rappend(afdt_fd, iov, &sz);
recv(afdt_fd, iov);
iov.clear();
h.resize(sz);
rappend(afdt_fd, iov, &h[0], sz * sizeof(h[0]));
recv(afdt_fd, iov, args...);
}
template<class... Tail>
void recv(int afdt_fd, std::vector<iovec>& iov,
std::vector<std::string>& h, Tail&... args) {
size_t sz;
rappend(afdt_fd, iov, &sz);
recv(afdt_fd, iov);
iov.clear();
h.resize(sz);
for (auto& e : h) {
size_t strsz;
rappend(afdt_fd, iov, &strsz);
recv(afdt_fd, iov);
iov.clear();
e.resize(strsz);
rappend(afdt_fd, iov, &e[0], strsz);
}
recv(afdt_fd, iov, args...);
}
}
template<class Head, class... Tail>
void sendx(int afdt_fd, const Head& h, Tail&&... args) {
std::vector<iovec> iov;
detail::send(afdt_fd, iov, h, std::forward<Tail>(args)...);
}
template<class Head, class... Tail>
void recvx(int afdt_fd, Head& h, Tail&... args) {
std::vector<iovec> iov;
detail::recv(afdt_fd, iov, h, args...);
}
template<class Head, class... Tail>
int sendRaw(int afdt_fd, const Head& h, Tail&&... args) {
std::vector<iovec> iov;
try {
detail::send(afdt_fd, iov, h, std::forward<Tail>(args)...);
return 0;
} catch (const std::runtime_error& e) {
return -1;
}
}
template<class Head, class... Tail>
int recvRaw(int afdt_fd, Head& h, Tail&... args) {
std::vector<iovec> iov;
try {
detail::recv(afdt_fd, iov, h, args...);
return 0;
} catch (const std::runtime_error& e) {
return -1;
}
}
bool send_fd(int afdt_fd, int fd);
int recv_fd(int afdt_fd);
///////////////////////////////////////////////////////////////////////////////
}
}
#endif