Add an IPPrefix::forString parsing function.

This provides a way to parse IP prefixes from strings, and
addresses a TODO. Instead of reusing NetdConstants' parsePrefix
function, which it cannot depend on, it implements the parsing
using the IPAddress class in the same file and standard string
methods.

Bug: 153694684
Test: new unit tests
Original-Change: https://android-review.googlesource.com/1313840
Merged-In: I47b29c8525f3c0236e48b4bb8dbebb223e83bc31
Change-Id: I47b29c8525f3c0236e48b4bb8dbebb223e83bc31
diff --git a/libnetdutils/InternetAddresses.cpp b/libnetdutils/InternetAddresses.cpp
index 78d30b2..322f1b1 100644
--- a/libnetdutils/InternetAddresses.cpp
+++ b/libnetdutils/InternetAddresses.cpp
@@ -16,6 +16,8 @@
 
 #include "netdutils/InternetAddresses.h"
 
+#include <string>
+
 #include <android-base/stringprintf.h>
 #include <arpa/inet.h>
 #include <netdb.h>
@@ -123,6 +125,28 @@
     return mData == empty;
 }
 
+bool IPPrefix::forString(const std::string& repr, IPPrefix* prefix) {
+    size_t index = repr.find('/');
+    if (index == std::string::npos) return false;
+
+    // Parse the IP address.
+    IPAddress ip;
+    if (!IPAddress::forString(repr.substr(0, index), &ip)) return false;
+
+    // Parse the prefix length. Can't use base::ParseUint because it accepts non-base 10 input.
+    const char* prefixString = repr.c_str() + index + 1;
+    if (!isdigit(*prefixString)) return false;
+    char* endptr;
+    unsigned long prefixlen = strtoul(prefixString, &endptr, 10);
+    if (*endptr != '\0') return false;
+
+    uint8_t maxlen = (ip.family() == AF_INET) ? 32 : 128;
+    if (prefixlen > maxlen) return false;
+
+    *prefix = IPPrefix(ip, prefixlen);
+    return true;
+}
+
 std::string IPPrefix::toString() const noexcept {
     return StringPrintf("%s/%d", ip().toString().c_str(), mData.cidrlen);
 }