BUG-2825: move code around and improve hex lookup 70/35370/5
authorRobert Varga <robert.varga@pantheon.sk>
Thu, 25 Feb 2016 01:44:43 +0000 (02:44 +0100)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 25 Feb 2016 15:23:29 +0000 (15:23 +0000)
This patch moves the individual blocks around so we end up with faster
hex lookup.

Change-Id: Ib2e2043f9d4dd28c77fe36012eb21506cad14687
Signed-off-by: Robert Varga <robert.varga@pantheon.sk>
model/ietf/ietf-type-util/src/main/java/org/opendaylight/mdsal/model/ietf/util/AbstractIetfYangUtil.java
model/ietf/ietf-type-util/src/main/java/org/opendaylight/mdsal/model/ietf/util/Ipv6Utils.java

index c2748a596cb552ba20b87ba5db72e312bd75c72b..dc1d8bc73a748e89cc520724cdda61ba9fe01a70 100644 (file)
@@ -125,7 +125,7 @@ public abstract class AbstractIetfYangUtil<T> {
         return factory.newInstance(bytesToString(bytes));
     }
 
-    private static byte hexValue(final char c) {
+    static byte hexValue(final char c) {
         byte v;
         try {
             // Performance optimization: access the array and rely on the VM for catching
index 867daa75e2fe0eee6088b1492d2788b07af2471d..9a26ad45358cd4669abaad934519b79c6dc28818 100644 (file)
@@ -8,9 +8,11 @@
 package org.opendaylight.mdsal.model.ietf.util;
 
 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 javax.annotation.Nonnull;
 
 /**
  * IPv6 address parsing for ietf-inet-types ipv6-address and ipv6-prefix. This is an internal implementation
@@ -58,68 +60,35 @@ final class Ipv6Utils {
      *
      * FIXME: rovarga: this looks wrong
      * @return - byte array of size 16. Last byte contains netmask
+     *
+     * @throws NullPointerException if ipv6address is null
      */
-   public static byte[] bytesForString(final String ipv6Address) {
-       /*
-        * Do not modify this routine to take direct strings input!!!
-        * Key checks have been removed based on the assumption that
-        * the input is validated via regexps in Ipv6Prefix()
-        */
-
-       String [] address =  (ipv6Address).split("%");
-
-       int colonp;
-       char ch;
-       boolean saw_xdigit;
-
-       /* Isn't it fun - the above variable names are the same in BSD and Sun sources */
-
-       int val;
+   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);
 
-       char[] src = address[0].toCharArray();
-
-       byte[] dst = new byte[INADDR6SZ];
-
-       int src_length = src.length;
-
-       colonp = -1;
-       int i = 0, j = 0;
+       // FIXME: fixme: use address.charAt() instead
+       char[] src = address.toCharArray();
 
        /* Leading :: requires some special handling. */
-
-       /* Isn't it fun - the above comment is again the same in BSD and Sun sources,
-        * We will derive our code from BSD. Shakespear always sounds better
-        * in original Clingon. So does Dilbert.
-        */
-
+       int i = 0;
        if (src[i] == ':') {
-           Preconditions.checkArgument(src[++i] == ':', "Invalid v6 address");
+           Preconditions.checkArgument(src[++i] == ':', "Invalid v6 address '%s'", ipv6Address);
        }
 
-       int curtok = i;
-       saw_xdigit = false;
-
+       final byte[] dst = new byte[INADDR6SZ];
 
-       val = 0;
+       final int src_length = src.length;
+       boolean saw_xdigit = false;
+       int val = 0;
+       int colonp = -1;
+       int j = 0;
+       int curtok = i;
        while (i < src_length) {
-           ch = src[i++];
-           int chval = Character.digit(ch, 16);
-
-           /* 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.
-            */
-
-           if (chval != -1) {
-               val <<= 4;
-               val |= chval;
-               saw_xdigit = true;
-               continue;
-           }
+           final char ch = src[i++];
 
            /* v6 separator */
-
            if (ch == ':') {
                curtok = i;
                if (!saw_xdigit) {
@@ -138,18 +107,15 @@ final class Ipv6Utils {
            }
 
            /* 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
-                * defficiencies as the java v6 implementation we can invoke it
+                * deficiencies as the java v6 implementation we can invoke it
                 * straight away and be done with it
                 */
-
-               Preconditions.checkArgument(j != (INADDR6SZ - INADDR4SZ - 1), "Invalid v4 in v6 mapping");
-
-               InetAddress _inet_form = InetAddresses.forString(address[0].substring(curtok, src_length));
+               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);
@@ -158,18 +124,27 @@ final class Ipv6Utils {
                saw_xdigit = false;
                break;
            }
-           /* removed parser exit on invalid char - no need to do it, regexp checks it */
+
+           /* 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;
        }
+
        if (saw_xdigit) {
-           Preconditions.checkArgument(j + INT16SZ <= INADDR6SZ, "Overrun in v6 parsing, should not occur");
+           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 (colonp != -1) {
-           int n = j - colonp;
+           Verify.verify(j != INADDR6SZ, "Overrun in parsing of '%s', should not occur", ipv6Address);
 
-           Preconditions.checkArgument(j != INADDR6SZ, "Overrun in v6 parsing, should not occur");
+           final int n = j - colonp;
            for (i = 1; i <= n; i++) {
                dst[INADDR6SZ - i] = dst[colonp + n - i];
                dst[colonp + n - i] = 0;
@@ -177,9 +152,7 @@ final class Ipv6Utils {
            j = INADDR6SZ;
        }
 
-       Preconditions.checkArgument(j == INADDR6SZ, "Overrun in v6 parsing, should not occur");
-
+       Verify.verify(j == INADDR6SZ, "Overrun in parsing of '%s', should not occur", ipv6Address);
        return dst;
    }
-
 }