Skip to content

Commit 0b5c3ea

Browse files
committed
Use a signed int for the pointers rather than a long since we can't use a 32bit address space anyway. Refactored some methods to make them a bit clearer
1 parent e55e7b4 commit 0b5c3ea

4 files changed

Lines changed: 87 additions & 88 deletions

File tree

src/main/java/com/maxmind/maxminddb/Decoder.java

Lines changed: 47 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ public static Type fromControlByte(int b) {
5454

5555
class Result {
5656
private final JsonNode node;
57-
private long offset;
57+
private int offset;
5858

59-
Result(JsonNode node, long offset) {
59+
Result(JsonNode node, int offset) {
6060
this.node = node;
6161
this.offset = offset;
6262
}
@@ -65,11 +65,11 @@ JsonNode getNode() {
6565
return this.node;
6666
}
6767

68-
long getOffset() {
68+
int getOffset() {
6969
return this.offset;
7070
}
7171

72-
void setOffset(long offset) {
72+
void setOffset(int offset) {
7373
this.offset = offset;
7474
}
7575

@@ -82,39 +82,32 @@ void setOffset(long offset) {
8282
this.DEBUG = System.getenv().get("MAXMIND_DB_DECODER_DEBUG") != null;
8383
}
8484

85-
Result decode(long offset) throws IOException {
85+
Result decode(int offset) throws IOException {
8686
ByteBuffer buffer = this.threadBuffer.get();
8787

88-
buffer.position((int) offset);
89-
90-
if (this.DEBUG) {
91-
Log.debug("Offset", String.valueOf(offset));
92-
}
93-
88+
buffer.position(offset);
9489
int ctrlByte = 0xFF & buffer.get();
95-
9690
offset++;
9791

98-
if (this.DEBUG) {
99-
Log.debugBinary("Control byte", ctrlByte);
100-
}
101-
10292
Type type = Type.fromControlByte(ctrlByte);
10393

10494
if (this.DEBUG) {
95+
Log.debug("Offset", String.valueOf(offset));
96+
Log.debugBinary("Control byte", ctrlByte);
10597
Log.debug("Type", type.name());
10698
}
10799

108100
// Pointers are a special case, we don't read the next $size bytes, we
109-
// use
110-
// the size to determine the length of the pointer and then follow it.
101+
// use the size to determine the length of the pointer and then follow
102+
// it.
111103
if (type.equals(Type.POINTER)) {
112104
Result pointer = this.decodePointer(ctrlByte, offset);
113105

106+
// for unit testing
114107
if (this.POINTER_TEST_HACK) {
115108
return pointer;
116109
}
117-
Result result = this.decode((pointer.getNode().asLong()));
110+
Result result = this.decode((pointer.getNode().asInt()));
118111
result.setOffset(pointer.getOffset());
119112
return result;
120113
}
@@ -139,38 +132,33 @@ Result decode(long offset) throws IOException {
139132
offset++;
140133
}
141134

142-
// consider passing by reference or something once I have a better feel
143-
// for the logic
144-
long[] sizeArray = this.sizeFromCtrlByte(ctrlByte, offset);
145-
int size = (int) sizeArray[0];
135+
int[] sizeArray = this.sizeFromCtrlByte(ctrlByte, offset);
136+
int size = sizeArray[0];
146137
offset = sizeArray[1];
147138

148139
if (this.DEBUG) {
149140
Log.debug("Size", String.valueOf(size));
150141
}
151142

152-
// The map and array types are special cases, since we don't read the
153-
// next
154-
// <code>size</code> bytes. For all other types, we do.
155-
if (type.equals(Type.MAP)) {
156-
return this.decodeMap(size, offset);
157-
}
158-
159-
if (type.equals(Type.ARRAY)) {
160-
return this.decodeArray(size, offset);
161-
}
162-
163-
if (type.equals(Type.BOOLEAN)) {
164-
return this.decodeBoolean(size, offset);
165-
}
166-
167143
if (this.DEBUG) {
168144
Log.debug("Offset", offset);
169145
Log.debug("Size", size);
170146
}
147+
return this.decodeByType(type, offset, size);
148+
}
171149

172-
long newOffset = offset + size;
150+
private Result decodeByType(Type type, int offset, int size)
151+
throws IOException {
152+
// MAP, ARRAY, and BOOLEAN do not use newOffset as we don't read the
153+
// next <code>size</code> bytes. For all other types, we do.
154+
int newOffset = offset + size;
173155
switch (type) {
156+
case MAP:
157+
return this.decodeMap(size, offset);
158+
case ARRAY:
159+
return this.decodeArray(size, offset);
160+
case BOOLEAN:
161+
return this.decodeBoolean(size, offset);
174162
case UTF8_STRING:
175163
TextNode s = new TextNode(this.decodeString(size));
176164
return new Result(s, newOffset);
@@ -203,10 +191,10 @@ Result decode(long offset) throws IOException {
203191
}
204192
}
205193

206-
private final long[] pointerValueOffset = { 0, 0, 1 << 11,
207-
(((long) 1) << 19) + ((1) << 11), 0 };
194+
private final int[] pointerValueOffset = { 0, 0, 1 << 11,
195+
(1 << 19) + ((1) << 11), 0 };
208196

209-
private Result decodePointer(int ctrlByte, long offset) {
197+
private Result decodePointer(int ctrlByte, int offset) {
210198

211199
int pointerSize = ((ctrlByte >>> 3) & 0x3) + 1;
212200

@@ -216,7 +204,7 @@ private Result decodePointer(int ctrlByte, long offset) {
216204

217205
int base = pointerSize == 4 ? (byte) 0 : (byte) (ctrlByte & 0x7);
218206

219-
long packed = this.decodeLong(base, pointerSize);
207+
int packed = this.decodeInteger(base, pointerSize);
220208

221209
if (this.DEBUG) {
222210
Log.debug("Packed pointer", String.valueOf(packed));
@@ -249,9 +237,9 @@ private IntNode decodeInt32(int size) {
249237
return new IntNode(this.decodeInteger(size));
250238
}
251239

252-
private int decodeInteger(int size) {
240+
private long decodeLong(int size) {
253241
ByteBuffer buffer = this.threadBuffer.get();
254-
int integer = 0;
242+
long integer = 0;
255243
for (int i = 0; i < size; i++) {
256244
integer = (integer << 8) | (buffer.get() & 0xFF);
257245
}
@@ -262,22 +250,22 @@ private LongNode decodeUint32(int size) {
262250
return new LongNode(this.decodeLong(size));
263251
}
264252

265-
private long decodeLong(int size) {
266-
return this.decodeLong(0, size);
253+
private int decodeInteger(int size) {
254+
return this.decodeInteger(0, size);
267255
}
268256

269-
private long decodeLong(long base, int size) {
257+
private int decodeInteger(int base, int size) {
270258
ByteBuffer buffer = this.threadBuffer.get();
271-
return Decoder.decodeLong(buffer, base, size);
259+
return Decoder.decodeInteger(buffer, base, size);
272260
}
273261

274-
static long decodeLong(ByteBuffer buffer, long base, int size) {
262+
static int decodeInteger(ByteBuffer buffer, int base, int size) {
275263

276-
long longInt = base;
264+
int integer = base;
277265
for (int i = 0; i < size; i++) {
278-
longInt = (longInt << 8) | (buffer.get() & 0xFF);
266+
integer = (integer << 8) | (buffer.get() & 0xFF);
279267
}
280-
return longInt;
268+
return integer;
281269
}
282270

283271
private BigIntegerNode decodeBigInteger(int size) {
@@ -293,13 +281,13 @@ private FloatNode decodeFloat() {
293281
return new FloatNode(this.threadBuffer.get().getFloat());
294282
}
295283

296-
private Result decodeBoolean(long size, long offset) {
284+
private Result decodeBoolean(int size, int offset) {
297285
BooleanNode b = size == 0 ? BooleanNode.FALSE : BooleanNode.TRUE;
298286

299287
return new Result(b, offset);
300288
}
301289

302-
private Result decodeArray(long size, long offset) throws IOException {
290+
private Result decodeArray(int size, int offset) throws IOException {
303291
if (this.DEBUG) {
304292
Log.debug("Array size", size);
305293
}
@@ -323,7 +311,7 @@ private Result decodeArray(long size, long offset) throws IOException {
323311
return new Result(array, offset);
324312
}
325313

326-
private Result decodeMap(long size, long offset) throws IOException {
314+
private Result decodeMap(int size, int offset) throws IOException {
327315
if (this.DEBUG) {
328316
Log.debug("Map size", size);
329317
}
@@ -354,11 +342,11 @@ private Result decodeMap(long size, long offset) throws IOException {
354342

355343
}
356344

357-
private long[] sizeFromCtrlByte(int ctrlByte, long offset) {
345+
private int[] sizeFromCtrlByte(int ctrlByte, int offset) {
358346
int size = ctrlByte & 0x1f;
359347

360348
if (size < 29) {
361-
return new long[] { size, offset };
349+
return new int[] { size, offset };
362350
}
363351

364352
int bytesToRead = size - 28;
@@ -375,7 +363,7 @@ private long[] sizeFromCtrlByte(int ctrlByte, long offset) {
375363
size = 65821 + i;
376364
}
377365

378-
return new long[] { size, offset + bytesToRead };
366+
return new int[] { size, offset + bytesToRead };
379367
}
380368

381369
private byte[] getByteArray(int length) {

0 commit comments

Comments
 (0)