Skip to content

Commit 5232d42

Browse files
committed
Fixed encoding and decoding of negative and infinity real numbers
... in Java library
1 parent ef5d5fd commit 5232d42

File tree

10 files changed

+102
-30
lines changed

10 files changed

+102
-30
lines changed

JavaLibrary/src/main/java/org/bn/coders/ber/BERDecoder.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -295,22 +295,19 @@ public DecodedObject<Double> decodeReal(DecodedObject<Integer> decodedTag, Class
295295
int realPreamble = stream.read();
296296

297297
Double result = 0.0D;
298-
int szResult = len.getValue();
299-
if ((realPreamble & 0x40) == 1) {
298+
if (realPreamble == 0x40) {
300299
// 01000000 Value is PLUS-INFINITY
301300
result = Double.POSITIVE_INFINITY;
302-
}
303-
if ((realPreamble & 0x41) == 1) {
301+
} else if (realPreamble == 0x41) {
304302
// 01000001 Value is MINUS-INFINITY
305303
result = Double.NEGATIVE_INFINITY;
306-
szResult += 1;
307304
} else if (len.getValue() > 0) {
308305
int szOfExp = 1 + (realPreamble & 0x3);
309306
int sign = realPreamble & 0x40;
310307
int ff = (realPreamble & 0x0C) >> 2;
311308
DecodedObject<Long> exponentEncFrm = decodeLongValue(stream, new DecodedObject<>(szOfExp));
312309
long exponent = exponentEncFrm.getValue();
313-
DecodedObject<Long> mantissaEncFrm = decodeLongValue(stream, new DecodedObject<>(szResult - szOfExp - 1));
310+
DecodedObject<Long> mantissaEncFrm = decodeLongValue(stream, new DecodedObject<>(len.getValue() - szOfExp - 1));
314311
// Unpack mantissa & decrement exponent for base 2
315312
long mantissa = mantissaEncFrm.getValue() << ff;
316313
while ((mantissa & 0x000ff00000000000L) == 0x0) {
@@ -324,7 +321,7 @@ public DecodedObject<Double> decodeReal(DecodedObject<Integer> decodedTag, Class
324321
mantissa &= 0x0FFFFFFFFFFFFFL;
325322
long lValue = (exponent + 1023 + 52) << 52;
326323
lValue |= mantissa;
327-
if (sign == 1) {
324+
if (sign == 0x40) {
328325
lValue |= 0x8000000000000000L;
329326
}
330327
result = Double.longBitsToDouble(lValue);

JavaLibrary/src/main/java/org/bn/coders/ber/BEREncoder.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,11 @@ public int encodeReal(Object object, OutputStream stream, ElementInfo elementInf
140140
long asLong = Double.doubleToLongBits(value);
141141
if (asLong == 0x7ff0000000000000L) { // positive infinity
142142
stream.write(0x40); // 01000000 Value is PLUS-INFINITY
143+
szOfInt = 1;
143144
} else if (asLong == 0xfff0000000000000L) { // negative infinity
144145
stream.write(0x41); // 01000001 Value is MINUS-INFINITY
145-
} else if (asLong != 0x0) {
146+
szOfInt = 1;
147+
} else if (asLong != 0) {
146148
long exponent = ((0x7ff0000000000000L & asLong) >> 52) - 1023 - 52;
147149
long mantissa = 0x000fffffffffffffL & asLong;
148150
mantissa |= 0x10000000000000L; // set virtual delimeter
@@ -161,19 +163,16 @@ public int encodeReal(Object object, OutputStream stream, ElementInfo elementInf
161163
int szOfExp = CoderUtils.getIntegerLength(exponent);
162164
szOfInt += encodeIntegerValue(exponent, stream);
163165

164-
int realPreamble = 0x80;
165-
realPreamble |= (byte) (szOfExp - 1);
166-
if ((asLong & 0x8000000000000000L) == 1) {
166+
int realPreamble = 0x80 | (byte)(szOfExp - 1);
167+
if ((asLong & 0x8000000000000000L) == 0x8000000000000000L) {
167168
realPreamble |= 0x40; // Sign
168169
}
169170
stream.write(realPreamble);
170171
szOfInt += 1;
171172
}
172173
resultSize += szOfInt;
173174
resultSize += encodeLength(szOfInt, stream);
174-
resultSize += encodeTag(BERCoderUtils.getTagValueForElement(elementInfo, TagClass.Universal, ElementType.Primitive, UniversalTag.Real),
175-
stream
176-
);
175+
resultSize += encodeTag(BERCoderUtils.getTagValueForElement(elementInfo, TagClass.Universal, ElementType.Primitive, UniversalTag.Real), stream);
177176
return resultSize;
178177
}
179178

JavaLibrary/src/main/java/org/bn/coders/per/PERAlignedDecoder.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -466,21 +466,18 @@ public DecodedObject<Double> decodeReal(DecodedObject<Integer> decodedTag, Class
466466
skipAlignedBits(stream);
467467

468468
Double result = 0.0D;
469-
int szResult = len;
470-
if ((realPreamble & 0x40) == 1) {
469+
if (realPreamble == 0x40) {
471470
// 01000000 Value is PLUS-INFINITY
472471
result = Double.POSITIVE_INFINITY;
473-
}
474-
if ((realPreamble & 0x41) == 1) {
472+
} else if (realPreamble == 0x41) {
475473
// 01000001 Value is MINUS-INFINITY
476474
result = Double.NEGATIVE_INFINITY;
477-
szResult += 1;
478475
} else if (len > 0) {
479476
int szOfExp = 1 + (realPreamble & 0x3);
480477
int sign = realPreamble & 0x40;
481478
int ff = (realPreamble & 0x0C) >> 2;
482479
long exponent = decodeIntegerValueAsBytes(szOfExp, stream);
483-
long mantissaEncFrm = decodeIntegerValueAsBytes(szResult - szOfExp - 1, stream);
480+
long mantissaEncFrm = decodeIntegerValueAsBytes(len - szOfExp - 1, stream);
484481
// Unpack mantissa & decrement exponent for base 2
485482
long mantissa = mantissaEncFrm << ff;
486483
while ((mantissa & 0x000ff00000000000L) == 0x0) {
@@ -494,13 +491,12 @@ public DecodedObject<Double> decodeReal(DecodedObject<Integer> decodedTag, Class
494491
mantissa &= 0x0FFFFFFFFFFFFFL;
495492
long lValue = (exponent + 1023 + 52) << 52;
496493
lValue |= mantissa;
497-
if (sign == 1) {
494+
if (sign == 0x40) {
498495
lValue |= 0x8000000000000000L;
499496
}
500497
result = Double.longBitsToDouble(lValue);
501498
}
502-
return new DecodedObject<>(result, szResult);
503-
499+
return new DecodedObject<>(result, len);
504500
}
505501

506502
@Override

JavaLibrary/src/main/java/org/bn/coders/per/PERAlignedEncoder.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -292,28 +292,27 @@ public int encodeReal(Object object, OutputStream stream, ElementInfo elementInf
292292
doAlign(stream);
293293
stream.write(0x41); // 01000001 Value is MINUS-INFINITY
294294
result += 1;
295-
} else if (asLong != 0x0) {
295+
} else if (asLong != 0) {
296296
long exponent = ((0x7ff0000000000000L & asLong) >> 52) - 1023 - 52;
297297
long mantissa = 0x000fffffffffffffL & asLong;
298298
mantissa |= 0x10000000000000L; // set virtual delimeter
299299

300300
// pack mantissa for base 2
301-
while ((mantissa & 0xFFL) == 0x0) {
301+
while ((mantissa & 0xFFL) == 0) {
302302
mantissa >>= 8;
303303
exponent += 8; //increment exponent to 8 (base 2)
304304
}
305-
while ((mantissa & 0x01L) == 0x0) {
305+
while ((mantissa & 0x01L) == 0) {
306306
mantissa >>= 1;
307307
exponent += 1; //increment exponent to 1
308308
}
309309

310310
int szOfExp = CoderUtils.getIntegerLength(exponent);
311311
encodeLengthDeterminant(CoderUtils.getIntegerLength(mantissa) + szOfExp + 1, bitStream);
312312
doAlign(stream);
313-
int realPreamble = 0x80;
314-
315-
realPreamble |= (byte) (szOfExp - 1);
316-
if ((asLong & 0x8000000000000000L) == 1) {
313+
314+
int realPreamble = 0x80 | (byte)(szOfExp - 1);
315+
if ((asLong & 0x8000000000000000L) == 0x8000000000000000L) {
317316
realPreamble |= 0x40; // Sign
318317
}
319318
stream.write(realPreamble);

JavaLibrary/src/test/java/org/bn/coders/CoderTestUtilities.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,24 @@ public TestReal createTestRealBig() {
471471
}
472472

473473
public abstract byte[] createTestRealBigBytes();
474+
475+
public TestReal createTestRealPosInf() {
476+
return new TestReal(Double.POSITIVE_INFINITY);
477+
}
478+
479+
public abstract byte[] createTestRealPosInfBytes();
480+
481+
public TestReal createTestRealNegInf() {
482+
return new TestReal(Double.NEGATIVE_INFINITY);
483+
}
484+
485+
public abstract byte[] createTestRealNegInfBytes();
486+
487+
public TestReal createTestRealNeg1_5() {
488+
return new TestReal(-1.5);
489+
}
490+
491+
public abstract byte[] createTestRealNeg1_5Bytes();
474492

475493
public TestLongTag createTestLongTag() {
476494
TestLongTag result = new TestLongTag();

JavaLibrary/src/test/java/org/bn/coders/DecoderTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,18 @@ public void testDecodeReal() throws Exception {
352352
stream = new ByteArrayInputStream(coderTestUtils.createTestRealBigBytes());
353353
val = decoder.decode(stream, TestReal.class);
354354
assertEquals(val.getValue(), coderTestUtils.createTestRealBig().getValue());
355+
356+
stream = new ByteArrayInputStream(coderTestUtils.createTestRealPosInfBytes());
357+
val = decoder.decode(stream, TestReal.class);
358+
assertEquals(val.getValue(), coderTestUtils.createTestRealPosInf().getValue());
359+
360+
stream = new ByteArrayInputStream(coderTestUtils.createTestRealNegInfBytes());
361+
val = decoder.decode(stream, TestReal.class);
362+
assertEquals(val.getValue(), coderTestUtils.createTestRealNegInf().getValue());
363+
364+
stream = new ByteArrayInputStream(coderTestUtils.createTestRealNeg1_5Bytes());
365+
val = decoder.decode(stream, TestReal.class);
366+
assertEquals(val.getValue(), coderTestUtils.createTestRealNeg1_5().getValue());
355367
}
356368

357369
@Test

JavaLibrary/src/test/java/org/bn/coders/EncoderTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,12 @@ public void testEncodeReals() throws Exception {
314314
checkEncoded(encoder, coderTestUtils.createTestReal2(), coderTestUtils.createTestReal2Bytes());
315315
printEncoded("EncodeTestRealBig: ",encoder, coderTestUtils.createTestRealBig());
316316
checkEncoded(encoder, coderTestUtils.createTestRealBig(), coderTestUtils.createTestRealBigBytes());
317+
printEncoded("EncodeTestRealPosInf: ",encoder, coderTestUtils.createTestRealPosInf());
318+
checkEncoded(encoder, coderTestUtils.createTestRealPosInf(), coderTestUtils.createTestRealPosInfBytes());
319+
printEncoded("EncodeTestRealNegInf: ",encoder, coderTestUtils.createTestRealNegInf());
320+
checkEncoded(encoder, coderTestUtils.createTestRealNegInf(), coderTestUtils.createTestRealNegInfBytes());
321+
printEncoded("EncodeTestReal-1.5: ",encoder, coderTestUtils.createTestRealNeg1_5());
322+
checkEncoded(encoder, coderTestUtils.createTestRealNeg1_5(), coderTestUtils.createTestRealNeg1_5Bytes());
317323
}
318324

319325
@Test

JavaLibrary/src/test/java/org/bn/coders/ber/BERCoderTestUtils.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,21 @@ public byte[] createTestReal2Bytes() {
281281
public byte[] createTestRealBigBytes() {
282282
return new byte[]{0x09, 0x05, (byte) 0x80, (byte) 0xFD, 0x18, 0x6D, 0x21};
283283
}
284+
285+
@Override
286+
public byte[] createTestRealPosInfBytes() {
287+
return new byte[] {0x09, 0x01, 0x40};
288+
}
289+
290+
@Override
291+
public byte[] createTestRealNegInfBytes() {
292+
return new byte[] {0x09, 0x01, 0x41};
293+
}
294+
295+
@Override
296+
public byte[] createTestRealNeg1_5Bytes() {
297+
return new byte[] {0x09, 0x03, (byte)0xC0, (byte)0xFF, 0x03};
298+
}
284299

285300
@Override
286301
public byte[] createChoiceInChoice2Bytes() {

JavaLibrary/src/test/java/org/bn/coders/per/PERAlignedCoderTestUtils.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,21 @@ public byte[] createTestReal2Bytes() {
237237
public byte[] createTestRealBigBytes() {
238238
return new byte[]{0x05, (byte) 0x80, (byte) 0xFD, 0x18, 0x6D, 0x21};
239239
}
240+
241+
@Override
242+
public byte[] createTestRealPosInfBytes() {
243+
return new byte[] {0x01, 0x40};
244+
}
245+
246+
@Override
247+
public byte[] createTestRealNegInfBytes() {
248+
return new byte[] {0x01, 0x41};
249+
}
250+
251+
@Override
252+
public byte[] createTestRealNeg1_5Bytes() {
253+
return new byte[] {0x03, (byte) 0xC0, (byte) 0xFF, 0x03};
254+
}
240255

241256
@Override
242257
public byte[] createChoiceInChoice2Bytes() {

JavaLibrary/src/test/java/org/bn/coders/per/PERUnalignedCoderTestUtils.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,21 @@ public byte[] createTestReal2Bytes() {
244244
public byte[] createTestRealBigBytes() {
245245
return new byte[]{0x05, (byte) 0x80, (byte) 0xFD, 0x18, 0x6D, 0x21};
246246
}
247+
248+
@Override
249+
public byte[] createTestRealPosInfBytes() {
250+
return new byte[] {0x01, 0x40};
251+
}
252+
253+
@Override
254+
public byte[] createTestRealNegInfBytes() {
255+
return new byte[] {0x01, 0x41};
256+
}
257+
258+
@Override
259+
public byte[] createTestRealNeg1_5Bytes() {
260+
return new byte[] {0x03, (byte) 0xC0, (byte) 0xFF, 0x03};
261+
}
247262

248263
@Override
249264
public byte[] createChoiceInChoice2Bytes() {

0 commit comments

Comments
 (0)