Work on #9 - group BCD routines in a convenience class
This commit is contained in:
@@ -23,6 +23,7 @@ import java.io.OutputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import com.solab.iso8583.util.Bcd;
|
||||
import com.solab.iso8583.util.HexCodec;
|
||||
|
||||
/** Represents a value that is stored in a field inside an ISO8583 message.
|
||||
@@ -291,7 +292,7 @@ public class IsoValue<T> implements Cloneable {
|
||||
}
|
||||
//Encode in BCD if it's one of these types
|
||||
if (buf != null) {
|
||||
toBcd(toString(), buf);
|
||||
Bcd.encode(toString(), buf);
|
||||
outs.write(buf);
|
||||
return;
|
||||
}
|
||||
@@ -316,24 +317,4 @@ public class IsoValue<T> implements Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
/** Encode the value as BCD and put it in the buffer. The buffer must be big enough
|
||||
* to store the digits in the original value (half the length of the string). */
|
||||
private void toBcd(String value, byte[] buf) {
|
||||
int charpos = 0; //char where we start
|
||||
int bufpos = 0;
|
||||
if (value.length() % 2 == 1) {
|
||||
//for odd lengths we encode just the first digit in the first byte
|
||||
buf[0] = (byte)(value.charAt(0) - 48);
|
||||
charpos = 1;
|
||||
bufpos = 1;
|
||||
}
|
||||
//encode the rest of the string
|
||||
while (charpos < value.length()) {
|
||||
buf[bufpos] = (byte)(((value.charAt(charpos) - 48) << 4)
|
||||
| (value.charAt(charpos + 1) - 48));
|
||||
charpos += 2;
|
||||
bufpos++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.text.ParseException;
|
||||
import com.solab.iso8583.CustomField;
|
||||
import com.solab.iso8583.IsoType;
|
||||
import com.solab.iso8583.IsoValue;
|
||||
import com.solab.iso8583.util.Bcd;
|
||||
|
||||
/** This class is used to parse NUMERIC fields.
|
||||
*
|
||||
@@ -49,30 +50,18 @@ public class NumericParseInfo extends AlphaNumericFieldParseInfo {
|
||||
}
|
||||
//A long covers up to 18 digits
|
||||
if (length < 19) {
|
||||
long l = 0;
|
||||
long power = 1L;
|
||||
for (int i = pos + (length / 2) + (length % 2) - 1; i >= pos; i--) {
|
||||
l += (buf[i] & 0x0f) * power;
|
||||
power *= 10L;
|
||||
l += ((buf[i] & 0xf0) >> 4) * power;
|
||||
power *= 10L;
|
||||
}
|
||||
return new IsoValue<Number>(IsoType.NUMERIC, l, length, null);
|
||||
return new IsoValue<Number>(IsoType.NUMERIC, Bcd.decodeToLong(buf, pos, length),
|
||||
length, null);
|
||||
} else {
|
||||
//Use a BigInteger
|
||||
char[] digits = new char[length];
|
||||
int start = 0;
|
||||
try {
|
||||
for (int i = pos; i < pos + (length / 2) + (length % 2); i++) {
|
||||
digits[start++] = (char)(((buf[i] & 0xf0) >> 4) + 48);
|
||||
digits[start++] = (char)((buf[i] & 0x0f) + 48);
|
||||
}
|
||||
return new IsoValue<Number>(IsoType.NUMERIC,
|
||||
Bcd.decodeToBigInteger(buf, pos, length), length, null);
|
||||
} catch (IndexOutOfBoundsException ex) {
|
||||
throw new ParseException(String.format(
|
||||
"Insufficient data for bin %s field %d of length %d, pos %d",
|
||||
type, field, length, pos), pos);
|
||||
"Insufficient data for bin %s field %d of length %d, pos %d",
|
||||
type, field, length, pos), pos);
|
||||
}
|
||||
return new IsoValue<Number>(IsoType.NUMERIC, new BigInteger(new String(digits)), length, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.solab.iso8583.util;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* Routines for Binary Coded Digits.
|
||||
*
|
||||
* @author Enrique Zamudio
|
||||
* Date: 23/04/13 11:24
|
||||
*/
|
||||
public final class Bcd {
|
||||
|
||||
private Bcd(){}
|
||||
|
||||
public static long decodeToLong(byte[] buf, int pos, int length)
|
||||
throws IndexOutOfBoundsException {
|
||||
if (length > 18) {
|
||||
throw new IndexOutOfBoundsException("Buffer too big to decode as long");
|
||||
}
|
||||
long l = 0;
|
||||
long power = 1L;
|
||||
for (int i = pos + (length / 2) + (length % 2) - 1; i >= pos; i--) {
|
||||
l += (buf[i] & 0x0f) * power;
|
||||
power *= 10L;
|
||||
l += ((buf[i] & 0xf0) >> 4) * power;
|
||||
power *= 10L;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
/** Encode the value as BCD and put it in the buffer. The buffer must be big enough
|
||||
* to store the digits in the original value (half the length of the string). */
|
||||
public static void encode(String value, byte[] buf) {
|
||||
int charpos = 0; //char where we start
|
||||
int bufpos = 0;
|
||||
if (value.length() % 2 == 1) {
|
||||
//for odd lengths we encode just the first digit in the first byte
|
||||
buf[0] = (byte)(value.charAt(0) - 48);
|
||||
charpos = 1;
|
||||
bufpos = 1;
|
||||
}
|
||||
//encode the rest of the string
|
||||
while (charpos < value.length()) {
|
||||
buf[bufpos] = (byte)(((value.charAt(charpos) - 48) << 4)
|
||||
| (value.charAt(charpos + 1) - 48));
|
||||
charpos += 2;
|
||||
bufpos++;
|
||||
}
|
||||
}
|
||||
|
||||
public static BigInteger decodeToBigInteger(byte[] buf, int pos, int length)
|
||||
throws IndexOutOfBoundsException {
|
||||
char[] digits = new char[length];
|
||||
int start = 0;
|
||||
for (int i = pos; i < pos + (length / 2) + (length % 2); i++) {
|
||||
digits[start++] = (char)(((buf[i] & 0xf0) >> 4) + 48);
|
||||
digits[start++] = (char)((buf[i] & 0x0f) + 48);
|
||||
}
|
||||
return new BigInteger(new String(digits));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user