Created
April 25, 2022 13:30
-
-
Save hasselmm/15af40abcec65f01b0899fd7eea3827d to your computer and use it in GitHub Desktop.
User defined literal for IPv4 addresses
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
#include <stdint.h> | |
namespace detail { | |
constexpr uint8_t parse_octet(const char *str, const char *end, const char **out = nullptr) | |
{ | |
uint8_t octet = 0; | |
if (str < end) { | |
if (*str >= '3' && *str <= '9') { // 3-9 | 30-99 | |
octet = static_cast<uint8_t>(*str++ - '0'); | |
if (str < end && *str >= '0' && *str <= '9') { // --- | 30-99 | |
octet *= 10; | |
octet += static_cast<uint8_t>(*str++ - '0'); | |
} | |
} else if (*str == '2') { // 2 | 20-29 | 200-255 | |
octet = static_cast<uint8_t>(*str++ - '0'); | |
if (str < end) { | |
if (*str >= '0' && *str <= '4') { // --- | 20-24 | 200-249 | |
octet *= 10; | |
octet += static_cast<uint8_t>(*str++ - '0'); | |
if (str < end && *str >= '0' && *str <= '9') { // --- | ----- | 200-249 | |
octet *= 10; | |
octet += static_cast<uint8_t>(*str++ - '0'); | |
} | |
} else if (*str == '5') { // --- | 25 | 250-255 | |
octet *= 10; | |
octet += static_cast<uint8_t>(*str++ - '0'); | |
if (str < end && *str >= '0' && *str <= '5') { // --- | ----- | 250-255 | |
octet *= 10; | |
octet += static_cast<uint8_t>(*str++ - '0'); | |
} | |
} else if (*str >= '6' && *str <= '9') { // --- | 26-29 | ------- | |
octet *= 10; | |
octet += static_cast<uint8_t>(*str++ - '0'); | |
} | |
} | |
} else if (*str == '1') { // 1 | 10-19 | 100-199 | |
octet = static_cast<uint8_t>(*str++ - '0'); | |
if (str < end && *str >= '0' && *str <= '9') { // --- | 10-19 | 100-199 | |
octet *= 10; | |
octet += static_cast<uint8_t>(*str++ - '0'); | |
if (str < end && *str >= '0' && *str <= '9') { // --- | ----- | 100-199 | |
octet *= 10; | |
octet += static_cast<uint8_t>(*str++ - '0'); | |
} | |
} | |
} else if (*str == '0') { // 0 | ----- | ------- | |
octet = static_cast<uint8_t>(*str++ - '0'); | |
} | |
} | |
if (out) | |
*out = str; | |
return octet; | |
} | |
template<size_t N> | |
constexpr uint8_t parse_octet(const char (& str)[N]) | |
{ | |
return parse_octet(str, str + N - 1); | |
} | |
static_assert(parse_octet("0") == 0); static_assert(parse_octet("1") == 1); static_assert(parse_octet("2") == 2); | |
static_assert(parse_octet("3") == 3); static_assert(parse_octet("4") == 4); static_assert(parse_octet("5") == 5); | |
static_assert(parse_octet("6") == 6); static_assert(parse_octet("7") == 7); static_assert(parse_octet("8") == 8); | |
static_assert(parse_octet("9") == 9); static_assert(parse_octet("10") == 10); static_assert(parse_octet("11") == 11); | |
static_assert(parse_octet("12") == 12); static_assert(parse_octet("13") == 13); static_assert(parse_octet("14") == 14); | |
static_assert(parse_octet("15") == 15); static_assert(parse_octet("16") == 16); static_assert(parse_octet("17") == 17); | |
static_assert(parse_octet("18") == 18); static_assert(parse_octet("19") == 19); static_assert(parse_octet("20") == 20); | |
static_assert(parse_octet("21") == 21); static_assert(parse_octet("22") == 22); static_assert(parse_octet("23") == 23); | |
static_assert(parse_octet("24") == 24); static_assert(parse_octet("25") == 25); static_assert(parse_octet("26") == 26); | |
static_assert(parse_octet("27") == 27); static_assert(parse_octet("28") == 28); static_assert(parse_octet("29") == 29); | |
static_assert(parse_octet("30") == 30); static_assert(parse_octet("31") == 31); static_assert(parse_octet("32") == 32); | |
static_assert(parse_octet("33") == 33); static_assert(parse_octet("34") == 34); static_assert(parse_octet("35") == 35); | |
static_assert(parse_octet("36") == 36); static_assert(parse_octet("37") == 37); static_assert(parse_octet("38") == 38); | |
static_assert(parse_octet("39") == 39); static_assert(parse_octet("40") == 40); static_assert(parse_octet("41") == 41); | |
static_assert(parse_octet("42") == 42); static_assert(parse_octet("43") == 43); static_assert(parse_octet("44") == 44); | |
static_assert(parse_octet("45") == 45); static_assert(parse_octet("46") == 46); static_assert(parse_octet("47") == 47); | |
static_assert(parse_octet("48") == 48); static_assert(parse_octet("49") == 49); static_assert(parse_octet("50") == 50); | |
static_assert(parse_octet("51") == 51); static_assert(parse_octet("52") == 52); static_assert(parse_octet("53") == 53); | |
static_assert(parse_octet("54") == 54); static_assert(parse_octet("55") == 55); static_assert(parse_octet("56") == 56); | |
static_assert(parse_octet("57") == 57); static_assert(parse_octet("58") == 58); static_assert(parse_octet("59") == 59); | |
static_assert(parse_octet("60") == 60); static_assert(parse_octet("61") == 61); static_assert(parse_octet("62") == 62); | |
static_assert(parse_octet("63") == 63); static_assert(parse_octet("64") == 64); static_assert(parse_octet("65") == 65); | |
static_assert(parse_octet("66") == 66); static_assert(parse_octet("67") == 67); static_assert(parse_octet("68") == 68); | |
static_assert(parse_octet("69") == 69); static_assert(parse_octet("70") == 70); static_assert(parse_octet("71") == 71); | |
static_assert(parse_octet("72") == 72); static_assert(parse_octet("73") == 73); static_assert(parse_octet("74") == 74); | |
static_assert(parse_octet("75") == 75); static_assert(parse_octet("76") == 76); static_assert(parse_octet("77") == 77); | |
static_assert(parse_octet("78") == 78); static_assert(parse_octet("79") == 79); static_assert(parse_octet("80") == 80); | |
static_assert(parse_octet("81") == 81); static_assert(parse_octet("82") == 82); static_assert(parse_octet("83") == 83); | |
static_assert(parse_octet("84") == 84); static_assert(parse_octet("85") == 85); static_assert(parse_octet("86") == 86); | |
static_assert(parse_octet("87") == 87); static_assert(parse_octet("88") == 88); static_assert(parse_octet("89") == 89); | |
static_assert(parse_octet("90") == 90); static_assert(parse_octet("91") == 91); static_assert(parse_octet("92") == 92); | |
static_assert(parse_octet("93") == 93); static_assert(parse_octet("94") == 94); static_assert(parse_octet("95") == 95); | |
static_assert(parse_octet("96") == 96); static_assert(parse_octet("97") == 97); static_assert(parse_octet("98") == 98); | |
static_assert(parse_octet("99") == 99); static_assert(parse_octet("100") == 100); static_assert(parse_octet("101") == 101); | |
static_assert(parse_octet("102") == 102); static_assert(parse_octet("103") == 103); static_assert(parse_octet("104") == 104); | |
static_assert(parse_octet("105") == 105); static_assert(parse_octet("106") == 106); static_assert(parse_octet("107") == 107); | |
static_assert(parse_octet("108") == 108); static_assert(parse_octet("109") == 109); static_assert(parse_octet("110") == 110); | |
static_assert(parse_octet("111") == 111); static_assert(parse_octet("112") == 112); static_assert(parse_octet("113") == 113); | |
static_assert(parse_octet("114") == 114); static_assert(parse_octet("115") == 115); static_assert(parse_octet("116") == 116); | |
static_assert(parse_octet("117") == 117); static_assert(parse_octet("118") == 118); static_assert(parse_octet("119") == 119); | |
static_assert(parse_octet("120") == 120); static_assert(parse_octet("121") == 121); static_assert(parse_octet("122") == 122); | |
static_assert(parse_octet("123") == 123); static_assert(parse_octet("124") == 124); static_assert(parse_octet("125") == 125); | |
static_assert(parse_octet("126") == 126); static_assert(parse_octet("127") == 127); static_assert(parse_octet("128") == 128); | |
static_assert(parse_octet("129") == 129); static_assert(parse_octet("130") == 130); static_assert(parse_octet("131") == 131); | |
static_assert(parse_octet("132") == 132); static_assert(parse_octet("133") == 133); static_assert(parse_octet("134") == 134); | |
static_assert(parse_octet("135") == 135); static_assert(parse_octet("136") == 136); static_assert(parse_octet("137") == 137); | |
static_assert(parse_octet("138") == 138); static_assert(parse_octet("139") == 139); static_assert(parse_octet("140") == 140); | |
static_assert(parse_octet("141") == 141); static_assert(parse_octet("142") == 142); static_assert(parse_octet("143") == 143); | |
static_assert(parse_octet("144") == 144); static_assert(parse_octet("145") == 145); static_assert(parse_octet("146") == 146); | |
static_assert(parse_octet("147") == 147); static_assert(parse_octet("148") == 148); static_assert(parse_octet("149") == 149); | |
static_assert(parse_octet("150") == 150); static_assert(parse_octet("151") == 151); static_assert(parse_octet("152") == 152); | |
static_assert(parse_octet("153") == 153); static_assert(parse_octet("154") == 154); static_assert(parse_octet("155") == 155); | |
static_assert(parse_octet("156") == 156); static_assert(parse_octet("157") == 157); static_assert(parse_octet("158") == 158); | |
static_assert(parse_octet("159") == 159); static_assert(parse_octet("160") == 160); static_assert(parse_octet("161") == 161); | |
static_assert(parse_octet("162") == 162); static_assert(parse_octet("163") == 163); static_assert(parse_octet("164") == 164); | |
static_assert(parse_octet("165") == 165); static_assert(parse_octet("166") == 166); static_assert(parse_octet("167") == 167); | |
static_assert(parse_octet("168") == 168); static_assert(parse_octet("169") == 169); static_assert(parse_octet("170") == 170); | |
static_assert(parse_octet("171") == 171); static_assert(parse_octet("172") == 172); static_assert(parse_octet("173") == 173); | |
static_assert(parse_octet("174") == 174); static_assert(parse_octet("175") == 175); static_assert(parse_octet("176") == 176); | |
static_assert(parse_octet("177") == 177); static_assert(parse_octet("178") == 178); static_assert(parse_octet("179") == 179); | |
static_assert(parse_octet("180") == 180); static_assert(parse_octet("181") == 181); static_assert(parse_octet("182") == 182); | |
static_assert(parse_octet("183") == 183); static_assert(parse_octet("184") == 184); static_assert(parse_octet("185") == 185); | |
static_assert(parse_octet("186") == 186); static_assert(parse_octet("187") == 187); static_assert(parse_octet("188") == 188); | |
static_assert(parse_octet("189") == 189); static_assert(parse_octet("190") == 190); static_assert(parse_octet("191") == 191); | |
static_assert(parse_octet("192") == 192); static_assert(parse_octet("193") == 193); static_assert(parse_octet("194") == 194); | |
static_assert(parse_octet("195") == 195); static_assert(parse_octet("196") == 196); static_assert(parse_octet("197") == 197); | |
static_assert(parse_octet("198") == 198); static_assert(parse_octet("199") == 199); static_assert(parse_octet("200") == 200); | |
static_assert(parse_octet("201") == 201); static_assert(parse_octet("202") == 202); static_assert(parse_octet("203") == 203); | |
static_assert(parse_octet("204") == 204); static_assert(parse_octet("205") == 205); static_assert(parse_octet("206") == 206); | |
static_assert(parse_octet("207") == 207); static_assert(parse_octet("208") == 208); static_assert(parse_octet("209") == 209); | |
static_assert(parse_octet("210") == 210); static_assert(parse_octet("211") == 211); static_assert(parse_octet("212") == 212); | |
static_assert(parse_octet("213") == 213); static_assert(parse_octet("214") == 214); static_assert(parse_octet("215") == 215); | |
static_assert(parse_octet("216") == 216); static_assert(parse_octet("217") == 217); static_assert(parse_octet("218") == 218); | |
static_assert(parse_octet("219") == 219); static_assert(parse_octet("220") == 220); static_assert(parse_octet("221") == 221); | |
static_assert(parse_octet("222") == 222); static_assert(parse_octet("223") == 223); static_assert(parse_octet("224") == 224); | |
static_assert(parse_octet("225") == 225); static_assert(parse_octet("226") == 226); static_assert(parse_octet("227") == 227); | |
static_assert(parse_octet("228") == 228); static_assert(parse_octet("229") == 229); static_assert(parse_octet("230") == 230); | |
static_assert(parse_octet("231") == 231); static_assert(parse_octet("232") == 232); static_assert(parse_octet("233") == 233); | |
static_assert(parse_octet("234") == 234); static_assert(parse_octet("235") == 235); static_assert(parse_octet("236") == 236); | |
static_assert(parse_octet("237") == 237); static_assert(parse_octet("238") == 238); static_assert(parse_octet("239") == 239); | |
static_assert(parse_octet("240") == 240); static_assert(parse_octet("241") == 241); static_assert(parse_octet("242") == 242); | |
static_assert(parse_octet("243") == 243); static_assert(parse_octet("244") == 244); static_assert(parse_octet("245") == 245); | |
static_assert(parse_octet("246") == 246); static_assert(parse_octet("247") == 247); static_assert(parse_octet("248") == 248); | |
static_assert(parse_octet("249") == 249); static_assert(parse_octet("250") == 250); static_assert(parse_octet("251") == 251); | |
static_assert(parse_octet("252") == 252); static_assert(parse_octet("253") == 253); static_assert(parse_octet("254") == 254); | |
static_assert(parse_octet("255") == 255); | |
} // namespace detail | |
constexpr uint32_t operator""_ipv4(const char *str, size_t len) | |
{ | |
const auto end = str + len; | |
auto ipv4 = uint32_t{}; | |
for (int i = 0; i < 3; ++i) { | |
ipv4 |= detail::parse_octet(str, end, &str); | |
ipv4 <<= 8; | |
if (str >= end || *str++ != '.') | |
return 0; | |
} | |
ipv4 |= detail::parse_octet(str, end, &str); | |
if (str != end) | |
return 0; | |
return ipv4; | |
} | |
static_assert("127.0.0.1"_ipv4 == 0x7f'00'00'01); | |
static_assert("192.168.0.15"_ipv4 == 0xC0'A8'00'0f); | |
static_assert("192.168.0.20"_ipv4 == 0xC0'A8'00'14); | |
static_assert("192.168.0.31"_ipv4 == 0xC0'A8'00'1f); | |
static_assert("192.168.0.255"_ipv4 == 0xC0'A8'00'ff); | |
static_assert("192.168.0.111"_ipv4 == 0xC0'A8'00'6f); | |
static_assert("192_168_0_111"_ipv4 == 0); | |
static_assert("192.168.0.111.1"_ipv4 == 0); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment