constexpr bool try_drop_prefix (std::size_t count) { const auto splitting = split_prefix(count); if (std::get<2>(splitting) == count) *this = std::get<1>(splitting); return std::get<2>(splitting) == count; }
constexpr bool try_drop_prefix (BoundedSequence<char32_t> prefix) { const auto splitting = split_prefix(std::move(prefix)); if (not std::get<2>(splitting)) *this = std::get<1>(splitting); return not std::get<2>(splitting); }
constexpr std::tuple<utf8_view, utf8_view> span_prefix (S characters) const { const auto splitting = split_prefix([characters=std::move(characters)](char32_t element) { return fold([element=std::move(element)](auto, auto character) { const auto isEqual = element == character; return std::make_tuple(isEqual, not isEqual); }, false, characters); }); return std::make_tuple(std::get<0>(splitting), std::get<1>(splitting)); }
constexpr bool match (S characters) const { const auto splitting = split_prefix(std::move(characters)); return not std::get<1>(splitting) and not std::get<2>(splitting); }
void drop_prefix (S other) { const auto splitting = split_prefix(std::move(other)); *this = std::get<1>(splitting); }
void drop_prefix (C predictor) { const auto splitting = split_prefix(std::move(predictor)); *this = std::get<1>(splitting); }
void take_prefix (S other) { const auto splitting = split_prefix(std::move(other)); *this = std::get<0>(splitting); }
static GPtrArray * read_ip6_routes (GKeyFile *file, const char *setting_name, const char *key) { GPtrArray *routes; struct in6_addr addr; guint32 prefix, metric; int i = 0; routes = g_ptr_array_sized_new (3); /* Look for individual routes */ while (i++ < 1000) { gchar **tmp; char *key_name, *str_prefix; gsize length = 0; int ret; GValueArray *values; GByteArray *address; GValue value = { 0 }; key_name = g_strdup_printf ("%s%d", key, i); tmp = g_key_file_get_string_list (file, setting_name, key_name, &length, NULL); g_free (key_name); if (!tmp || !length) break; /* all done */ if (length != 3) { g_warning ("%s: ignoring invalid IPv6 address item '%s'", __func__, key_name); goto next; } /* convert the string array into IPv6 routes */ values = g_value_array_new (4); /* NMIP6Route has 4 items */ /* Split the route and prefix */ str_prefix = split_prefix (tmp[0]); /* destination address */ ret = inet_pton (AF_INET6, tmp[0], &addr); if (ret <= 0) { g_warning ("%s: ignoring invalid IPv6 %s element '%s'", __func__, key_name, tmp[0]); g_value_array_free (values); goto next; } address = g_byte_array_new (); g_byte_array_append (address, (guint8 *) addr.s6_addr, 16); g_value_init (&value, DBUS_TYPE_G_UCHAR_ARRAY); g_value_take_boxed (&value, address); g_value_array_append (values, &value); g_value_unset (&value); /* prefix */ prefix = 0; if (str_prefix) { if (!get_one_int (str_prefix, 128, key_name, &prefix)) { g_value_array_free (values); goto next; } } else { /* default to 64 if unspecified */ prefix = 64; } g_value_init (&value, G_TYPE_UINT); g_value_set_uint (&value, prefix); g_value_array_append (values, &value); g_value_unset (&value); /* next hop address */ ret = inet_pton (AF_INET6, tmp[1], &addr); if (ret <= 0) { g_warning ("%s: ignoring invalid IPv6 %s element '%s'", __func__, key_name, tmp[1]); g_value_array_free (values); goto next; } address = g_byte_array_new (); g_byte_array_append (address, (guint8 *) addr.s6_addr, 16); g_value_init (&value, DBUS_TYPE_G_UCHAR_ARRAY); g_value_take_boxed (&value, address); g_value_array_append (values, &value); g_value_unset (&value); /* metric */ metric = 0; if (!get_one_int (tmp[2], G_MAXUINT32, key_name, &metric)) { g_value_array_free (values); goto next; } g_value_init (&value, G_TYPE_UINT); g_value_set_uint (&value, metric); g_value_array_append (values, &value); g_value_unset (&value); g_ptr_array_add (routes, values); next: g_strfreev (tmp); } if (routes->len < 1) { g_ptr_array_free (routes, TRUE); routes = NULL; } return routes; }
static GPtrArray * read_ip6_addresses (GKeyFile *file, const char *setting_name, const char *key) { GPtrArray *addresses; struct in6_addr addr, gw; guint32 prefix; int i = 0; addresses = g_ptr_array_sized_new (3); /* Look for individual addresses */ while (i++ < 1000) { char *tmp, *key_name, *str_prefix, *str_gw; int ret; GValueArray *values; GByteArray *address; GByteArray *gateway; GValue value = { 0 }; key_name = g_strdup_printf ("%s%d", key, i); tmp = g_key_file_get_string (file, setting_name, key_name, NULL); g_free (key_name); if (!tmp) break; /* all done */ /* convert the string array into IPv6 addresses */ values = g_value_array_new (2); /* NMIP6Address has 2 items */ /* Split the address and prefix */ str_prefix = split_prefix (tmp); /* address */ ret = inet_pton (AF_INET6, tmp, &addr); if (ret <= 0) { g_warning ("%s: ignoring invalid IPv6 %s element '%s'", __func__, key_name, tmp); g_value_array_free (values); goto next; } address = g_byte_array_new (); g_byte_array_append (address, (guint8 *) addr.s6_addr, 16); g_value_init (&value, DBUS_TYPE_G_UCHAR_ARRAY); g_value_take_boxed (&value, address); g_value_array_append (values, &value); g_value_unset (&value); /* prefix */ prefix = 0; if (str_prefix) { if (!get_one_int (str_prefix, 128, key_name, &prefix)) { g_value_array_free (values); goto next; } } else { /* Missing prefix defaults to /64 */ prefix = 64; } g_value_init (&value, G_TYPE_UINT); g_value_set_uint (&value, prefix); g_value_array_append (values, &value); g_value_unset (&value); /* Gateway (optional) */ str_gw = split_gw (str_prefix); if (str_gw) { ret = inet_pton (AF_INET6, str_gw, &gw); if (ret <= 0) { g_warning ("%s: ignoring invalid IPv6 %s gateway '%s'", __func__, key_name, tmp); g_value_array_free (values); goto next; } if (!IN6_IS_ADDR_UNSPECIFIED (&gw)) { gateway = g_byte_array_new (); g_byte_array_append (gateway, (guint8 *) gw.s6_addr, 16); g_value_init (&value, DBUS_TYPE_G_UCHAR_ARRAY); g_value_take_boxed (&value, gateway); g_value_array_append (values, &value); g_value_unset (&value); } } g_ptr_array_add (addresses, values); next: g_free (tmp); } if (addresses->len < 1) { g_ptr_array_free (addresses, TRUE); addresses = NULL; } return addresses; }