Skip to content

Commit cbb8d04

Browse files
eonwhitejyemin
andauthored
Improve performance of ObjectId#parseHexString (#1034)
JAVA-4816 Co-authored-by: Jeff Yemin <[email protected]>
1 parent dee0358 commit cbb8d04

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

bson/src/main/org/bson/types/ObjectId.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,17 +415,30 @@ private Object readResolve() {
415415
}
416416

417417
private static byte[] parseHexString(final String s) {
418-
if (!isValid(s)) {
419-
throw new IllegalArgumentException("invalid hexadecimal representation of an ObjectId: [" + s + "]");
420-
}
418+
notNull("hexString", s);
419+
isTrueArgument("hexString has 24 characters", s.length() == 24);
421420

422421
byte[] b = new byte[OBJECT_ID_LENGTH];
423422
for (int i = 0; i < b.length; i++) {
424-
b[i] = (byte) Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16);
423+
int pos = i << 1;
424+
char c1 = s.charAt(pos);
425+
char c2 = s.charAt(pos + 1);
426+
b[i] = (byte) ((hexCharToInt(c1) << 4) + hexCharToInt(c2));
425427
}
426428
return b;
427429
}
428430

431+
private static int hexCharToInt(final char c) {
432+
if (c >= '0' && c <= '9') {
433+
return c - 48;
434+
} else if (c >= 'a' && c <= 'f') {
435+
return c - 87;
436+
} else if (c >= 'A' && c <= 'F') {
437+
return c - 55;
438+
}
439+
throw new IllegalArgumentException("invalid hexadecimal character: [" + c + "]");
440+
}
441+
429442
private static int dateToTimestampSeconds(final Date time) {
430443
return (int) (time.getTime() / 1000);
431444
}

bson/src/test/unit/org/bson/types/ObjectIdTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@
2727
import java.text.ParseException;
2828
import java.text.SimpleDateFormat;
2929
import java.util.Date;
30+
import java.util.Locale;
3031
import java.util.Random;
3132

3233
import static org.junit.Assert.assertArrayEquals;
3334
import static org.junit.Assert.assertEquals;
35+
import static org.junit.Assert.assertThrows;
3436
import static org.junit.Assert.assertTrue;
3537
import static org.junit.Assert.fail;
3638

@@ -142,6 +144,10 @@ public void testDateCons() {
142144
public void testHexStringConstructor() {
143145
ObjectId id = new ObjectId();
144146
assertEquals(id, new ObjectId(id.toHexString()));
147+
assertEquals(id, new ObjectId(id.toHexString().toUpperCase(Locale.US)));
148+
assertThrows(IllegalArgumentException.class, () -> new ObjectId((String) null));
149+
assertThrows(IllegalArgumentException.class, () -> new ObjectId(id.toHexString().substring(0, 23)));
150+
assertThrows(IllegalArgumentException.class, () -> new ObjectId(id.toHexString().substring(0, 23) + '%'));
145151
}
146152

147153
@Test

0 commit comments

Comments
 (0)