import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
-import com.google.common.net.InetAddresses;
-import java.net.Inet4Address;
-import java.net.InetAddress;
+import java.util.Arrays;
import javax.annotation.Nonnull;
/**
/**
* Convert Ipv6Address object to a valid Canonical v6 address in byte format
*
- * @param ipv6Address - v6 Address object
- *
- * FIXME: rovarga: this looks wrong
- * @return - byte array of size 16. Last byte contains netmask
- *
+ * @param bytes Byte array for output
+ * @param str String representation
+ * @param strLimit String offset which should not be processed
* @throws NullPointerException if ipv6address is null
*/
- public static @Nonnull byte[] bytesForString(final @Nonnull String ipv6Address) {
- final int percentPos = ipv6Address.indexOf('%');
- // FIXME: do not perform a copy, just set the limit here.
- final String address = percentPos == -1 ? ipv6Address : ipv6Address.substring(0, percentPos);
-
- /* Leading :: requires some special handling. */
+ static void fillIpv6Bytes(final @Nonnull byte[] bytes, final String str, final int strLimit) {
+ // Leading :: requires some special handling.
int i = 0;
- if (address.charAt(i) == ':') {
+ if (str.charAt(i) == ':') {
// Note ++i side-effect in check
- Preconditions.checkArgument(address.charAt(++i) == ':', "Invalid v6 address '%s'", ipv6Address);
+ Preconditions.checkArgument(str.charAt(++i) == ':', "Invalid v6 address '%s'", str);
}
- final byte[] dst = new byte[INADDR6SZ];
-
- final int src_length = address.length();
- boolean saw_xdigit = false;
+ boolean haveVal = false;
int val = 0;
int colonp = -1;
int j = 0;
int curtok = i;
- while (i < src_length) {
- final char ch = address.charAt(i++);
+ while (i < strLimit) {
+ final char ch = str.charAt(i++);
- /* v6 separator */
+ // v6 separator
if (ch == ':') {
curtok = i;
- if (!saw_xdigit) {
- /* no need to check separator position validity - regexp does that */
+ if (haveVal) {
+ // removed overrun check - the regexp checks for valid data
+ bytes[j++] = (byte) ((val >>> 8) & 0xff);
+ bytes[j++] = (byte) (val & 0xff);
+ haveVal = false;
+ val = 0;
+ } else {
+ // no need to check separator position validity - regexp does that
colonp = j;
- continue;
}
- /* removed overrun check - the regexp checks for valid data */
-
- dst[j++] = (byte) ((val >>> 8) & 0xff);
- dst[j++] = (byte) (val & 0xff);
- saw_xdigit = false;
- val = 0;
continue;
}
- /* frankenstein - v4 attached to v6, mixed notation */
+ // frankenstein - v4 attached to v6, mixed notation
if (ch == '.' && ((j + INADDR4SZ) <= INADDR6SZ)) {
-
- /* this has passed the regexp so it is fairly safe to parse it
- * straight away. As v4 addresses do not suffer from the same
- * deficiencies as the java v6 implementation we can invoke it
- * straight away and be done with it
+ /*
+ * This has passed the regexp so it is fairly safe to parse it
+ * straight away. Use the Ipv4Utils for that.
*/
- Preconditions.checkArgument(j != (INADDR6SZ - INADDR4SZ - 1), "Invalid v4 in v6 mapping in %s", ipv6Address);
- InetAddress _inet_form = InetAddresses.forString(address.substring(curtok, src_length));
-
- Preconditions.checkArgument(_inet_form instanceof Inet4Address);
- System.arraycopy(_inet_form.getAddress(), 0, dst, j, INADDR4SZ);
+ Ipv4Utils.fillIpv4Bytes(bytes, j, str, curtok, strLimit);
j += INADDR4SZ;
-
- saw_xdigit = false;
+ haveVal = false;
break;
}
- /* Business as usual - ipv6 address digit.
+ /*
+ * Business as usual - ipv6 address digit.
* We can remove all checks from the original BSD code because
* the regexp has already verified that we are not being fed
* anything bigger than 0xffff between the separators.
*/
final int chval = AbstractIetfYangUtil.hexValue(ch);
val = (val << 4) | chval;
- saw_xdigit = true;
+ haveVal = true;
}
- if (saw_xdigit) {
- Verify.verify(j + INT16SZ <= INADDR6SZ, "Overrun in parsing of '%s', should not occur", ipv6Address);
- dst[j++] = (byte) ((val >> 8) & 0xff);
- dst[j++] = (byte) (val & 0xff);
+ if (haveVal) {
+ Verify.verify(j + INT16SZ <= INADDR6SZ, "Overrun in parsing of '%s', should not occur", str);
+ bytes[j++] = (byte) ((val >> 8) & 0xff);
+ bytes[j++] = (byte) (val & 0xff);
}
if (colonp != -1) {
- Verify.verify(j != INADDR6SZ, "Overrun in parsing of '%s', should not occur", ipv6Address);
-
- final int n = j - colonp;
- for (i = 1; i <= n; i++) {
- dst[INADDR6SZ - i] = dst[colonp + n - i];
- dst[colonp + n - i] = 0;
- }
- j = INADDR6SZ;
+ Verify.verify(j != INADDR6SZ, "Overrun in parsing of '%s', should not occur", str);
+ expandZeros(bytes, colonp, j);
+ } else {
+ Verify.verify(j == INADDR6SZ, "Overrun in parsing of '%s', should not occur", str);
}
-
- Verify.verify(j == INADDR6SZ, "Overrun in parsing of '%s', should not occur", ipv6Address);
- return dst;
}
+
+ private static void expandZeros(final byte[] bytes, final int where, final int filledBytes) {
+ final int tailLength = filledBytes - where;
+ final int tailOffset = INADDR6SZ - tailLength;
+ System.arraycopy(bytes, where, bytes, tailOffset, tailLength);
+ Arrays.fill(bytes, where, tailOffset, (byte)0);
+ }
}