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;
191
192 static {
193 byte[] ns = new byte[256];
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 NIBBLES = ns;
218 }
219
220 /**
221 * Creates a {@code UUID} from the string standard representation as
222 * described in the {@link #toString} method.
223 *
224 * @param name
225 * A string that specifies a {@code UUID}
226 *
227 * @return A {@code UUID} with the specified value
228 *
229 * @throws IllegalArgumentException
230 * If name does not conform to the string representation as
231 * described in {@link #toString}
232 *
233 */
234 public static UUID fromString(String name) {
235 if (name.length() == 36) {
236 char ch1 = name.charAt(8);
237 char ch2 = name.charAt(13);
238 char ch3 = name.charAt(18);
239 char ch4 = name.charAt(23);
240 if (ch1 == '-' && ch2 == '-' && ch3 == '-' && ch4 == '-') {
241 long msb1 = parse4Nibbles(name, 0);
242 long msb2 = parse4Nibbles(name, 4);
243 long msb3 = parse4Nibbles(name, 9);
244 long msb4 = parse4Nibbles(name, 14);
245 long lsb1 = parse4Nibbles(name, 19);
246 long lsb2 = parse4Nibbles(name, 24);
247 long lsb3 = parse4Nibbles(name, 28);
248 long lsb4 = parse4Nibbles(name, 32);
249 if ((msb1 | msb2 | msb3 | msb4 | lsb1 | lsb2 | lsb3 | lsb4) >= 0) {
250 return new UUID(
251 msb1 << 48 | msb2 << 32 | msb3 << 16 | msb4,
252 lsb1 << 48 | lsb2 << 32 | lsb3 << 16 | lsb4);
253 }
254 }
255 }
256 return fromString1(name);
257 }
258
259 private static long parse4Nibbles(String name, int pos) {
260 byte[] ns = NIBBLES;
261 char ch1 = name.charAt(pos);
262 char ch2 = name.charAt(pos + 1);
263 char ch3 = name.charAt(pos + 2);
264 char ch4 = name.charAt(pos + 3);
265 return (ch1 | ch2 | ch3 | ch4) > 0xff ?
266 -1 : ns[ch1] << 12 | ns[ch2] << 8 | ns[ch3] << 4 | ns[ch4];
267 }
268
269 private static UUID fromString1(String name) {
270 int len = name.length();
271 if (len > 36) {
272 throw new IllegalArgumentException("UUID string too large");
273 }
274
275 int dash1 = name.indexOf('-', 0);
276 int dash2 = name.indexOf('-', dash1 + 1);
277 int dash3 = name.indexOf('-', dash2 + 1);
278 int dash4 = name.indexOf('-', dash3 + 1);
279 int dash5 = name.indexOf('-', dash4 + 1);
280
281 // For any valid input, dash1 through dash4 will be positive and dash5
282 // negative, but it's enough to check dash4 and dash5:
283 // - if dash1 is -1, dash4 will be -1
284 // - if dash1 is positive but dash2 is -1, dash4 will be -1
285 // - if dash1 and dash2 is positive, dash3 will be -1, dash4 will be
286 // positive, but so will dash5
287 if (dash4 < 0 || dash5 >= 0) {
288 throw new IllegalArgumentException("Invalid UUID string: " + name);
289 }
|