Skip to content

Instantly share code, notes, and snippets.

@insooth
Created January 16, 2020 10:22
Show Gist options
  • Save insooth/b7c20d0cfb6d5f1fdaeae00d8ad2a492 to your computer and use it in GitHub Desktop.
Save insooth/b7c20d0cfb6d5f1fdaeae00d8ad2a492 to your computer and use it in GitHub Desktop.
Convert string to IP address -- mix compile time with runtime
#include <iostream>
#include <arpa/inet.h>
#include <string>
#include <type_traits>
#include <cassert>
#include <cstddef>
#include <array>
#include <utility>
enum class IpVersion { IPv4, IPv6 };
// ---
template<IpVersion v>
auto toIpAddress(const char* const s)
{
static_assert((IpVersion::IPv4 == v) || (IpVersion::IPv6 == v)
, "Unsupported IP version");
}
template<>
auto toIpAddress<IpVersion::IPv4>(const char* const s)
{
assert(s);
std::uint32_t buff;
const int r = inet_pton(AF_INET, s, &buff);
return std::make_pair(buff, static_cast<bool>(r));
}
template<>
auto toIpAddress<IpVersion::IPv6>(const char* const s)
{
assert(s);
std::array<std::uint8_t, sizeof(struct in6_addr)> buff;
const int r = inet_pton(AF_INET6, s, buff.data());
return std::make_pair(buff, static_cast<bool>(r));
}
// ---
template<class T, std::size_t N>
void show(const std::array<T, N>& xs)
{
using U = std::conditional_t<
std::is_same_v<std::make_unsigned_t<T>, std::uint8_t>
, std::size_t
, T
>;
for (auto&& x : xs)
{
std::cout << static_cast<U>(x) << ' ';
}
}
template<class T>
void show(T t) { std::cout << t; }
int main()
{
std::string s = "ff::00";
// std::string s = "192.168.11.22";
IpVersion v = IpVersion::IPv6;
if (v == IpVersion::IPv4)
{
auto&& [d, r] = toIpAddress<IpVersion::IPv4>(s.c_str());
if (r) { show(d); } else { std::cout << "error\n"; }
}
else
{
auto&& [d, r] = toIpAddress<IpVersion::IPv6>(s.c_str());
if (r) { show(d); } else { std::cout << "error\n"; }
}
return 0;
}
/*
http://coliru.stacked-crooked.com/a/c47248183a5c1eac
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment