-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
823 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
project(unistdpp) | ||
|
||
add_library(${PROJECT_NAME} STATIC | ||
unistdpp.cpp | ||
file.cpp | ||
pipe.cpp | ||
poll.cpp | ||
socket.cpp) | ||
|
||
target_include_directories(${PROJECT_NAME} | ||
PUBLIC | ||
${CMAKE_CURRENT_SOURCE_DIR}/include | ||
PRIVATE | ||
${CMAKE_CURRENT_SOURCE_DIR}) | ||
|
||
target_link_libraries(${PROJECT_NAME} PUBLIC tl::expected) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#include "unistdpp/file.h" | ||
|
||
namespace unistdpp { | ||
|
||
Result<std::string> | ||
readFile(const std::filesystem::path& path) { | ||
return open(path.c_str(), O_RDONLY).and_then([](auto fd) { | ||
std::string buf; | ||
return lseek(fd, 0, SEEK_END) | ||
.and_then([&](auto offset) { | ||
buf.resize(offset); | ||
return lseek(fd, 0, SEEK_SET); | ||
}) | ||
.and_then([&](auto) { return fd.readAll(buf.data(), buf.size()); }) | ||
.map([&buf]() { return std::move(buf); }); | ||
}); | ||
} | ||
|
||
} // namespace unistdpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#pragma once | ||
|
||
#include "traits.h" | ||
|
||
#include <tl/expected.hpp> | ||
|
||
#include <system_error> | ||
|
||
namespace error_details { | ||
template<typename T, typename E> | ||
constexpr auto | ||
getValue(tl::expected<T, E> v) { | ||
if constexpr (std::is_same_v<T, void>) { | ||
return; | ||
} else { | ||
return std::move(*v); | ||
} | ||
} | ||
} // namespace error_details | ||
|
||
#define TRY(x) \ | ||
({ \ | ||
auto&& xOrErr = x; \ | ||
if (!xOrErr.has_value()) { \ | ||
return tl::unexpected(xOrErr.error()); \ | ||
}; \ | ||
error_details::getValue(std::move(xOrErr)); \ | ||
}) | ||
|
||
namespace unistdpp { | ||
template<typename T> | ||
using Result = tl::expected<T, std::errc>; | ||
|
||
[[nodiscard]] inline std::errc | ||
getErrno() { | ||
return static_cast<std::errc>(errno); | ||
} | ||
|
||
inline std::string | ||
toString(std::errc error) { | ||
return std::make_error_code(error).message(); | ||
} | ||
|
||
template<typename T> | ||
struct WrapperTraits<Result<T>> { | ||
static_assert( | ||
std::is_integral_v<T>, | ||
"Please provide explicit wrapper trait for non integral results"); | ||
|
||
static Result<T> ret(T res) { | ||
if (res == -1) { | ||
return tl::unexpected(getErrno()); | ||
} | ||
return res; | ||
} | ||
}; | ||
|
||
template<> | ||
struct WrapperTraits<Result<void>> { | ||
static Result<void> ret(int res) { | ||
if (res == -1) { | ||
return tl::unexpected(getErrno()); | ||
} | ||
return {}; | ||
} | ||
}; | ||
|
||
} // namespace unistdpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#pragma once | ||
|
||
#include "unistdpp.h" | ||
|
||
#include <fcntl.h> | ||
#include <filesystem> | ||
|
||
namespace unistdpp { | ||
|
||
constexpr auto open = FnWrapper<::open, Result<FD>(const char*, int)>{}; | ||
constexpr auto lseek = | ||
FnWrapper<::lseek, Result<off_t>(const FD&, off_t, int)>{}; | ||
|
||
Result<std::string> | ||
readFile(const std::filesystem::path& path); | ||
|
||
} // namespace unistdpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#pragma once | ||
|
||
#include "unistdpp.h" | ||
|
||
#include <system_error> | ||
#include <tl/expected.hpp> | ||
|
||
namespace unistdpp { | ||
|
||
struct Pipe { | ||
FD readPipe; | ||
FD writePipe; | ||
}; | ||
|
||
Result<Pipe> | ||
pipe(); | ||
|
||
} // namespace unistdpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#pragma once | ||
|
||
#include "unistdpp.h" | ||
|
||
#include <chrono> | ||
#include <optional> | ||
#include <vector> | ||
|
||
#include <poll.h> | ||
|
||
namespace unistdpp { | ||
|
||
enum class Wait { | ||
READ = POLLIN, | ||
WRITE = POLLOUT, | ||
READ_WRITE = POLLIN | POLLOUT, | ||
}; | ||
|
||
inline pollfd | ||
waitFor(const FD& fd, Wait wait) { | ||
return pollfd{ .fd = fd.fd, .events = static_cast<short>(wait) }; | ||
} | ||
|
||
inline bool | ||
canRead(const pollfd& fd) { | ||
return (fd.revents & POLLIN) != 0; | ||
} | ||
|
||
inline bool | ||
canWrite(const pollfd& fd) { | ||
return (fd.revents & POLLOUT) != 0; | ||
} | ||
|
||
Result<int> | ||
poll(std::vector<pollfd>& pollfds, | ||
std::optional<std::chrono::milliseconds> timeout = std::nullopt); | ||
|
||
} // namespace unistdpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
#pragma once | ||
|
||
#include "traits.h" | ||
#include "unistdpp.h" | ||
|
||
#include <arpa/inet.h> | ||
#include <netinet/in.h> | ||
#include <sys/socket.h> | ||
#include <sys/un.h> | ||
|
||
#include <string_view> | ||
#include <tuple> | ||
#include <variant> | ||
|
||
namespace unistdpp { | ||
|
||
struct Address { | ||
static Address fromUnixPath(const char* path); | ||
static Address fromHostPort(int32_t host, int port); | ||
static Result<Address> fromHostPort(std::string_view host, int port); | ||
|
||
sockaddr* ptr() noexcept { return reinterpret_cast<sockaddr*>(&storage); } | ||
const sockaddr* ptr() const noexcept { | ||
return reinterpret_cast<const sockaddr*>(&storage); | ||
} | ||
|
||
sa_family_t type() const noexcept { return ptr()->sa_family; } | ||
|
||
socklen_t size() const noexcept { return addressSize; } | ||
|
||
std::aligned_union_t<0, sockaddr_un, sockaddr_in> storage; | ||
socklen_t addressSize = sizeof(storage); | ||
}; | ||
|
||
template<> | ||
struct WrapperTraits<const Address&> { | ||
static std::tuple<const sockaddr*, socklen_t> arg(const Address& addr) { | ||
return { addr.ptr(), addr.size() }; | ||
} | ||
}; | ||
|
||
template<> | ||
struct WrapperTraits<const Address*> { | ||
static std::tuple<const sockaddr*, socklen_t> arg(const Address* addr) { | ||
return { addr ? addr->ptr() : nullptr, addr ? addr->size() : 0 }; | ||
} | ||
}; | ||
|
||
template<> | ||
struct WrapperTraits<Address*> { | ||
static std::tuple<sockaddr*, socklen_t*> arg(Address* addr) { | ||
return { addr ? addr->ptr() : nullptr, | ||
addr ? &addr->addressSize : nullptr }; | ||
} | ||
}; | ||
|
||
// int | ||
// socket(int domain, int type, int protocol); | ||
constexpr auto socket = FnWrapper<::socket, Result<FD>(int, int, int)>{}; | ||
|
||
// int | ||
// setsockopt(int socket, int level, int option_name, | ||
// const void *option_value, socklen_t option_len); | ||
constexpr auto setsockopt = | ||
FnWrapper<::setsockopt, | ||
Result<void>(const FD&, int, int, const void*, socklen_t)>{}; | ||
|
||
// int | ||
// bind(int socket, const struct sockaddr *address, socklen_t address_len); | ||
constexpr auto bindRaw = | ||
FnWrapper<::bind, Result<void>(const FD& fd, const sockaddr*, socklen_t)>{}; | ||
constexpr auto bind = | ||
FnWrapper<::bind, Result<void>(const FD& fd, const Address&)>{}; | ||
|
||
// int | ||
// listen(int socket, int backlog); | ||
constexpr auto listen = FnWrapper<::listen, Result<void>(const FD&, int)>{}; | ||
|
||
// int | ||
// accept(int socket, struct sockaddr *restrict address, | ||
// socklen_t *restrict address_len); | ||
constexpr auto accept = | ||
FnWrapper<::accept, Result<FD>(const FD&, sockaddr*, socklen_t*)>{}; | ||
|
||
// int connect(int socket, const struct sockaddr *address, | ||
// socklen_t address_len); | ||
constexpr auto connectRaw = | ||
FnWrapper<::connect, Result<void>(const FD&, const sockaddr*, socklen_t)>{}; | ||
constexpr auto connect = | ||
FnWrapper<::connect, Result<void>(const FD&, const Address&)>{}; | ||
|
||
// ssize_t sendto(int socket, const void *message, size_t length, | ||
// int flags, const struct sockaddr *dest_addr, | ||
// socklen_t dest_len); | ||
constexpr auto sendto = FnWrapper< | ||
::sendto, | ||
Result<ssize_t>(const FD&, const void*, size_t, int, const Address*)>{}; | ||
|
||
// ssize_t recvfrom(int socket, void *restrict buffer, size_t length, | ||
// int flags, struct sockaddr *restrict address, | ||
// socklen_t *restrict address_len); | ||
constexpr auto recvfrom = | ||
FnWrapper<::recvfrom, | ||
Result<ssize_t>(const FD&, void*, size_t, int, Address*)>{}; | ||
} // namespace unistdpp |
Oops, something went wrong.