< prev index next >

src/java.base/share/classes/java/util/UUID.java

Print this page
rev 58200 : 8196334: Optimize UUID#fromString
Reviewed-by: TBD
Contributed-by: plokhotnyuk@gmail.com, jon.chambers@gmail.com, claes.redestad@oracle.com


 164      *         A byte array to be used to construct a {@code UUID}
 165      *
 166      * @return  A {@code UUID} generated from the specified array
 167      */
 168     public static UUID nameUUIDFromBytes(byte[] name) {
 169         MessageDigest md;
 170         try {
 171             md = MessageDigest.getInstance("MD5");
 172         } catch (NoSuchAlgorithmException nsae) {
 173             throw new InternalError("MD5 not supported", nsae);
 174         }
 175         byte[] md5Bytes = md.digest(name);
 176         md5Bytes[6]  &= 0x0f;  /* clear version        */
 177         md5Bytes[6]  |= 0x30;  /* set to version 3     */
 178         md5Bytes[8]  &= 0x3f;  /* clear variant        */
 179         md5Bytes[8]  |= 0x80;  /* set to IETF variant  */
 180         return new UUID(md5Bytes);
 181     }
 182 
 183     /**




































 184      * Creates a {@code UUID} from the string standard representation as
 185      * described in the {@link #toString} method.
 186      *
 187      * @param  name
 188      *         A string that specifies a {@code UUID}
 189      *
 190      * @return  A {@code UUID} with the specified value
 191      *
 192      * @throws  IllegalArgumentException
 193      *          If name does not conform to the string representation as
 194      *          described in {@link #toString}
 195      *
 196      */
 197     public static UUID fromString(String name) {


































 198         int len = name.length();
 199         if (len > 36) {
 200             throw new IllegalArgumentException("UUID string too large");
 201         }
 202 
 203         int dash1 = name.indexOf('-', 0);
 204         int dash2 = name.indexOf('-', dash1 + 1);
 205         int dash3 = name.indexOf('-', dash2 + 1);
 206         int dash4 = name.indexOf('-', dash3 + 1);
 207         int dash5 = name.indexOf('-', dash4 + 1);
 208 
 209         // For any valid input, dash1 through dash4 will be positive and dash5
 210         // negative, but it's enough to check dash4 and dash5:
 211         // - if dash1 is -1, dash4 will be -1
 212         // - if dash1 is positive but dash2 is -1, dash4 will be -1
 213         // - if dash1 and dash2 is positive, dash3 will be -1, dash4 will be
 214         //   positive, but so will dash5
 215         if (dash4 < 0 || dash5 >= 0) {
 216             throw new IllegalArgumentException("Invalid UUID string: " + name);
 217         }




 164      *         A byte array to be used to construct a {@code UUID}
 165      *
 166      * @return  A {@code UUID} generated from the specified array
 167      */
 168     public static UUID nameUUIDFromBytes(byte[] name) {
 169         MessageDigest md;
 170         try {
 171             md = MessageDigest.getInstance("MD5");
 172         } catch (NoSuchAlgorithmException nsae) {
 173             throw new InternalError("MD5 not supported", nsae);
 174         }
 175         byte[] md5Bytes = md.digest(name);
 176         md5Bytes[6]  &= 0x0f;  /* clear version        */
 177         md5Bytes[6]  |= 0x30;  /* set to version 3     */
 178         md5Bytes[8]  &= 0x3f;  /* clear variant        */
 179         md5Bytes[8]  |= 0x80;  /* set to IETF variant  */
 180         return new UUID(md5Bytes);
 181     }
 182 
 183     /**
 184      * Used by {@code fromString}. While {@code Character.digit(ch, 16)}
 185      * could be used to the same effect, benchmarks show specializing
 186      * for ASCII hex is still a small but significant gain. We should
 187      * examine if {@code Character.digit(ch, 16)} can be optimized and
 188      * this code replaced without adding any overhead.
 189      */
 190     private static final byte[] NIBBLES = new byte[256];
 191 
 192     static {
 193         byte[] ns = NIBBLES;
 194         java.util.Arrays.fill(ns, (byte) -1);
 195         ns['0'] = 0;
 196         ns['1'] = 1;
 197         ns['2'] = 2;
 198         ns['3'] = 3;
 199         ns['4'] = 4;
 200         ns['5'] = 5;
 201         ns['6'] = 6;
 202         ns['7'] = 7;
 203         ns['8'] = 8;
 204         ns['9'] = 9;
 205         ns['A'] = 10;
 206         ns['B'] = 11;
 207         ns['C'] = 12;
 208         ns['D'] = 13;
 209         ns['E'] = 14;
 210         ns['F'] = 15;
 211         ns['a'] = 10;
 212         ns['b'] = 11;
 213         ns['c'] = 12;
 214         ns['d'] = 13;
 215         ns['e'] = 14;
 216         ns['f'] = 15;
 217     }
 218 
 219     /**
 220      * Creates a {@code UUID} from the string standard representation as
 221      * described in the {@link #toString} method.
 222      *
 223      * @param  name
 224      *         A string that specifies a {@code UUID}
 225      *
 226      * @return  A {@code UUID} with the specified value
 227      *
 228      * @throws  IllegalArgumentException
 229      *          If name does not conform to the string representation as
 230      *          described in {@link #toString}
 231      *
 232      */
 233     public static UUID fromString(String name) {
 234         if (name.length() == 36) {
 235             long ch1 = name.charAt(8);
 236             long ch2 = name.charAt(13);
 237             long ch3 = name.charAt(18);
 238             long ch4 = name.charAt(23);
 239             if ((ch1 << 48 | ch2 << 32 | ch3 << 16 | ch4) == 0x2d002d002d002dL) {
 240                 long msb1 = parse4Nibbles(name, 0);
 241                 long msb2 = parse4Nibbles(name, 4);
 242                 long msb3 = parse4Nibbles(name, 9);
 243                 long msb4 = parse4Nibbles(name, 14);
 244                 long lsb1 = parse4Nibbles(name, 19);
 245                 long lsb2 = parse4Nibbles(name, 24);
 246                 long lsb3 = parse4Nibbles(name, 28);
 247                 long lsb4 = parse4Nibbles(name, 32);
 248                 if ((msb1 | msb2 | msb3 | msb4 | lsb1 | lsb2 | lsb3 | lsb4) >= 0) {
 249                     return new UUID(msb1 << 48 | msb2 << 32 | msb3 << 16 | msb4,
 250                             lsb1 << 48 | lsb2 << 32 | lsb3 << 16 | lsb4);
 251                 }
 252             }
 253         }
 254         return fromString1(name);
 255     }
 256 
 257     private static long parse4Nibbles(String name, int pos) {
 258         byte[] ns = NIBBLES;
 259         char ch1 = name.charAt(pos);
 260         char ch2 = name.charAt(pos + 1);
 261         char ch3 = name.charAt(pos + 2);
 262         char ch4 = name.charAt(pos + 3);
 263         return (ch1 | ch2 | ch3 | ch4) > 0xff ?
 264                 -1 : ns[ch1] << 12 | ns[ch2] << 8 | ns[ch3] << 4 | ns[ch4];
 265     }
 266 
 267     private static UUID fromString1(String name) {
 268         int len = name.length();
 269         if (len > 36) {
 270             throw new IllegalArgumentException("UUID string too large");
 271         }
 272 
 273         int dash1 = name.indexOf('-', 0);
 274         int dash2 = name.indexOf('-', dash1 + 1);
 275         int dash3 = name.indexOf('-', dash2 + 1);
 276         int dash4 = name.indexOf('-', dash3 + 1);
 277         int dash5 = name.indexOf('-', dash4 + 1);
 278 
 279         // For any valid input, dash1 through dash4 will be positive and dash5
 280         // negative, but it's enough to check dash4 and dash5:
 281         // - if dash1 is -1, dash4 will be -1
 282         // - if dash1 is positive but dash2 is -1, dash4 will be -1
 283         // - if dash1 and dash2 is positive, dash3 will be -1, dash4 will be
 284         //   positive, but so will dash5
 285         if (dash4 < 0 || dash5 >= 0) {
 286             throw new IllegalArgumentException("Invalid UUID string: " + name);
 287         }


< prev index next >