Skip to content

Commit

Permalink
Add Unicode parsing support for uint128_t.
Browse files Browse the repository at this point in the history
  • Loading branch information
VladimirShaleev committed May 27, 2024
1 parent 0c6c29c commit 215ec5a
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 121 deletions.
14 changes: 9 additions & 5 deletions include/ipaddress/base-v6.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@

namespace IPADDRESS_NAMESPACE {

namespace internal {

IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE bool is_invalid_scope_id_symbol(char c) IPADDRESS_NOEXCEPT {
return c == '%' || c == '/' || c == ' ' || (c >= '\t' && c <= '\r');
}

} // namespace IPADDRESS_NAMESPACE::internal

/**
* A template class providing the base functionality for IPv6 addresses.
*
Expand Down Expand Up @@ -279,10 +287,6 @@ class base_v6 {
return address;
}

IPADDRESS_NODISCARD static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE bool is_invalid_scope_id_symbol(char c) IPADDRESS_NOEXCEPT {
return c == '%' || c == '/' || c == ' ' || (c >= '\t' && c <= '\r');
}

private:
template <typename Iter>
struct ip_and_scope {
Expand All @@ -308,7 +312,7 @@ class base_v6 {
error = error_code::scope_id_is_too_long;
return result;
}
if (is_invalid_scope_id_symbol(c)) {
if (internal::is_invalid_scope_id_symbol(c)) {
error = error_code::invalid_scope_id;
return result;
}
Expand Down
7 changes: 1 addition & 6 deletions include/ipaddress/ip-any-address.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1143,12 +1143,7 @@ class ip_address {
*/
template <typename T, size_t N>
IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address parse(const T(&address)[N]) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
auto code = error_code::no_error;
auto result = internal::ip_any_parser<ip_address>::parse(address, code);
if (code != error_code::no_error) {
raise_error(code, 0, address, N);
}
return result;
return internal::ip_any_parser<ip_address>::parse(address);
}

/**
Expand Down
21 changes: 2 additions & 19 deletions include/ipaddress/ip-any-network.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1178,12 +1178,7 @@ class ip_network {
*/
template <typename T, size_t N>
IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_network parse(const T(&address)[N], bool strict = true) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
auto code = error_code::no_error;
auto result = internal::net_any_parser<ip_network>::parse(address, code, strict);
if (code != error_code::no_error) {
raise_error(code, 0, address, N);
}
return result;
return internal::net_any_parser<ip_network>::parse(address, strict);
}

/**
Expand All @@ -1201,19 +1196,7 @@ class ip_network {
*/
template <typename T, size_t N>
static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_network parse(const T(&address)[N], error_code& code, bool strict = true) IPADDRESS_NOEXCEPT {
code = error_code::no_error;

const auto net4 = ipv4_network::parse(address, code, strict);
if (code == error_code::no_error) {
return ip_network(net4);
}

const auto net6 = ipv6_network::parse(address, code, strict);
if (code == error_code::no_error) {
return ip_network(net6);
}

return ip_network();
return internal::net_any_parser<ip_network>::parse(address, code, strict);
}

/**
Expand Down
156 changes: 82 additions & 74 deletions include/ipaddress/ipv6-address.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,67 @@

namespace IPADDRESS_NAMESPACE {

namespace internal {

template <typename T>
struct ipv6_set_scope {
template <typename Str>
static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void change(fixed_string<IPADDRESS_IPV6_SCOPE_MAX_LENGTH>& result, const Str& scope) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
#if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
error_code code = error_code::no_error;
uint32_t index = 0;
change(result, scope, code, index);
#ifndef IPADDRESS_NO_EXCEPTIONS
if (code != error_code::no_error) {
raise_error(code, index, scope.data(), scope.size());
}
#endif // !IPADDRESS_NO_EXCEPTIONS
#endif // IPADDRESS_IPV6_SCOPE_MAX_LENGTH
}

template <typename Str>
static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void change(fixed_string<IPADDRESS_IPV6_SCOPE_MAX_LENGTH>& result, const Str& scope, error_code& code) IPADDRESS_NOEXCEPT {
#if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
uint32_t index = 0;
change(result, scope, code, index);
#endif // IPADDRESS_IPV6_SCOPE_MAX_LENGTH
}

template <typename Str>
static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void change(fixed_string<IPADDRESS_IPV6_SCOPE_MAX_LENGTH>& result, const Str& scope, error_code& code, uint32_t& index) IPADDRESS_NOEXCEPT {
#if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
char str[IPADDRESS_IPV6_SCOPE_MAX_LENGTH + 1] = {};
auto it = scope.data();
auto end = it + scope.size();
uint32_t error_symbol = 0;
code = error_code::no_error;
index = 0;
for (int i = 0; it < end; ++i) {
if (i > IPADDRESS_IPV6_SCOPE_MAX_LENGTH) {
code = error_code::scope_id_is_too_long;
return;
}
auto c = internal::next_char_or_error(it, end, code, error_symbol);
if (code != error_code::no_error) {
index = error_symbol;
return;
}
if (internal::is_invalid_scope_id_symbol(c)) {
code = error_code::invalid_scope_id;
return;
}
str[i] = c;
}
const auto fixed_scope = make_fixed_string(str, code);
if (code == error_code::no_error) {
result = fixed_scope;
}
#endif // IPADDRESS_IPV6_SCOPE_MAX_LENGTH
}
};

} // namespace IPADDRESS_NAMESPACE::internal

/**
* Represents the scope identifier for an IPv6 address.
*
Expand Down Expand Up @@ -251,10 +312,10 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
auto code = error_code::no_error;
const auto result = make_fixed_string(scope_id, code);
if (code == error_code::no_error) {
change_scope_id(result);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, result);
}
#else // !IPADDRESS_NO_EXCEPTIONS
change_scope_id(make_fixed_string(scope_id));
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, make_fixed_string(scope_id));
#endif // !IPADDRESS_NO_EXCEPTIONS
#endif // IPADDRESS_IPV6_SCOPE_MAX_LENGTH
}
Expand All @@ -277,7 +338,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
static_assert(N <= IPADDRESS_IPV6_SCOPE_MAX_LENGTH + 1, "scope id is too long");
const auto fixed_scope = make_fixed_string(scope_id, code);
if (code == error_code::no_error) {
change_scope_id(fixed_scope, code);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, fixed_scope, code);
}
#endif // IPADDRESS_IPV6_SCOPE_MAX_LENGTH
}
Expand All @@ -301,7 +362,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @endparblock
*/
IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void set_scope_id(std::string_view scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
change_scope_id(scope_id);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id);
}

/**
Expand All @@ -321,7 +382,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @endparblock
*/
IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void set_scope_id(std::wstring_view scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
change_scope_id(scope_id);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id);
}

#if __cpp_char8_t >= 201811L
Expand All @@ -338,7 +399,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
*/
IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void set_scope_id(std::u8string_view scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
change_scope_id(scope_id);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id);
}

#endif // __cpp_char8_t
Expand All @@ -360,7 +421,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @endparblock
*/
IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void set_scope_id(std::u16string_view scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
change_scope_id(scope_id);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id);
}

/**
Expand All @@ -380,7 +441,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @endparblock
*/
IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void set_scope_id(std::u32string_view scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
change_scope_id(scope_id);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id);
}

/**
Expand All @@ -399,7 +460,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @endparblock
*/
IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void set_scope_id(std::string_view scope_id, error_code& code) IPADDRESS_NOEXCEPT {
change_scope_id(scope_id, code);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id, code);
}

/**
Expand All @@ -418,7 +479,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @endparblock
*/
IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void set_scope_id(std::wstring_view scope_id, error_code& code) IPADDRESS_NOEXCEPT {
change_scope_id(scope_id, code);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id, code);
}

#if __cpp_char8_t >= 201811L
Expand All @@ -434,7 +495,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
*/
IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void set_scope_id(std::u8string_view scope_id, error_code& code) IPADDRESS_NOEXCEPT {
change_scope_id(scope_id, code);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id, code);
}

#endif // __cpp_char8_t
Expand All @@ -455,7 +516,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @endparblock
*/
IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void set_scope_id(std::u16string_view scope_id, error_code& code) IPADDRESS_NOEXCEPT {
change_scope_id(scope_id, code);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id, code);
}

/**
Expand All @@ -474,7 +535,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @endparblock
*/
IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void set_scope_id(std::u32string_view scope_id, error_code& code) IPADDRESS_NOEXCEPT {
change_scope_id(scope_id, code);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id, code);
}

#else // IPADDRESS_CPP_VERSION < 17
Expand All @@ -486,7 +547,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @throw parse_error Exception caused by invalid input string.
*/
IPADDRESS_FORCE_INLINE void set_scope_id(const std::string& scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
change_scope_id(scope_id);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id);
}

/**
Expand All @@ -496,7 +557,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @throw parse_error Exception caused by invalid input wide string.
*/
IPADDRESS_FORCE_INLINE void set_scope_id(const std::wstring& scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
change_scope_id(scope_id);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id);
}

/**
Expand All @@ -506,7 +567,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @throw parse_error Exception caused by invalid input UTF-16 string.
*/
IPADDRESS_FORCE_INLINE void set_scope_id(const std::u16string& scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
change_scope_id(scope_id);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id);
}

/**
Expand All @@ -516,7 +577,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @throw parse_error Exception caused by invalid input UTF-32 string.
*/
IPADDRESS_FORCE_INLINE void set_scope_id(const std::u32string& scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
change_scope_id(scope_id);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id);
}

/**
Expand All @@ -526,7 +587,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @param[out] code An error_code object that will store the result of the operation.
*/
IPADDRESS_FORCE_INLINE void set_scope_id(const std::string& scope_id, error_code& code) IPADDRESS_NOEXCEPT {
change_scope_id(scope_id, code);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id, code);
}

/**
Expand All @@ -536,7 +597,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @param[out] code An error_code object that will store the result of the operation.
*/
IPADDRESS_FORCE_INLINE void set_scope_id(const std::wstring& scope_id, error_code& code) IPADDRESS_NOEXCEPT {
change_scope_id(scope_id, code);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id, code);
}

/**
Expand All @@ -546,7 +607,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @param[out] code An error_code object that will store the result of the operation.
*/
IPADDRESS_FORCE_INLINE void set_scope_id(const std::u16string& scope_id, error_code& code) IPADDRESS_NOEXCEPT {
change_scope_id(scope_id, code);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id, code);
}

/**
Expand All @@ -556,7 +617,7 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
* @param[out] code An error_code object that will store the result of the operation.
*/
IPADDRESS_FORCE_INLINE void set_scope_id(const std::u32string& scope_id, error_code& code) IPADDRESS_NOEXCEPT {
change_scope_id(scope_id, code);
internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id, code);
}

#endif // IPADDRESS_CPP_VERSION < 17
Expand Down Expand Up @@ -759,59 +820,6 @@ class ipv6_address_base : public base_v6<ipv6_address_base> {
template <typename>
friend class ip_network_base;

template <typename Str>
IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void change_scope_id(const Str& scope) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
#if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
error_code code = error_code::no_error;
uint32_t index = 0;
change_scope_id(scope, code, index);
#ifndef IPADDRESS_NO_EXCEPTIONS
if (code != error_code::no_error) {
raise_error(code, index, scope.data(), scope.size());
}
#endif // !IPADDRESS_NO_EXCEPTIONS
#endif // IPADDRESS_IPV6_SCOPE_MAX_LENGTH
}

template <typename Str>
IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void change_scope_id(const Str& scope, error_code& code) IPADDRESS_NOEXCEPT {
#if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
uint32_t index = 0;
change_scope_id(scope, code, index);
#endif // IPADDRESS_IPV6_SCOPE_MAX_LENGTH
}

template <typename Str>
IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void change_scope_id(const Str& scope, error_code& code, uint32_t& index) IPADDRESS_NOEXCEPT {
#if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
char str[IPADDRESS_IPV6_SCOPE_MAX_LENGTH + 1] = {};
auto it = scope.data();
auto end = it + scope.size();
uint32_t error_symbol = 0;
index = 0;
for (int i = 0; it < end; ++i) {
if (i > IPADDRESS_IPV6_SCOPE_MAX_LENGTH) {
code = error_code::scope_id_is_too_long;
return;
}
auto c = internal::next_char_or_error(it, end, code, error_symbol);
if (code != error_code::no_error) {
index = error_symbol;
return;
}
if (base_v6<ipv6_address_base>::is_invalid_scope_id_symbol(c)) {
code = error_code::invalid_scope_id;
return;
}
str[i] = c;
}
const auto result = make_fixed_string(str, code);
if (code == error_code::no_error) {
_data.scope_id = result;
}
#endif // IPADDRESS_IPV6_SCOPE_MAX_LENGTH
}

struct ipv6_data {
IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ipv6_data() IPADDRESS_NOEXCEPT = default;
IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ipv6_data(const base_type& b) IPADDRESS_NOEXCEPT : bytes(b) {
Expand Down
Loading

0 comments on commit 215ec5a

Please sign in to comment.