summaryrefslogtreecommitdiffstats
path: root/src/net/gcdc/asn1/uper/BigIntCoder.java
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/net/gcdc/asn1/uper/BigIntCoder.java96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/net/gcdc/asn1/uper/BigIntCoder.java b/src/net/gcdc/asn1/uper/BigIntCoder.java
new file mode 100644
index 0000000..8c24eb7
--- /dev/null
+++ b/src/net/gcdc/asn1/uper/BigIntCoder.java
@@ -0,0 +1,96 @@
+package net.gcdc.asn1.uper;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.math.BigInteger;
+import net.gcdc.asn1.datatypes.Asn1BigInteger;
+import net.gcdc.asn1.datatypes.Asn1Default;
+import net.gcdc.asn1.datatypes.IntRange;
+
+class BigIntCoder implements Encoder, Decoder {
+
+ @Override public <T> boolean canDecode(Class<T> classOfT, Annotation[] extraAnnotations) {
+ return Asn1BigInteger.class.isAssignableFrom(classOfT);
+ }
+
+ @Override public <T> T decode(BitBuffer bitbuffer,
+ Class<T> classOfT, Field f,
+ Annotation[] extraAnnotations) {
+ AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(),
+ extraAnnotations);
+
+ String pos = String.format("%d.%d", bitbuffer.position()/8 , bitbuffer.position() % 8);
+ UperEncoder.logger.debug(String.format("Position %s BIG INT",pos));
+ IntRange intRange = annotations.getAnnotation(IntRange.class);
+ if (intRange != null && intRange.maxValue() > 0) {
+ throw new UnsupportedOperationException("Big int with upper range is not supported yet");
+ }
+
+ int lengthInOctets = (int) UperEncoder.decodeLengthDeterminant(bitbuffer);
+ BitBuffer valueBits = ByteBitBuffer.allocate(lengthInOctets * 8);
+ for (int i = 0; i < lengthInOctets * 8; i++) {
+ valueBits.put(bitbuffer.get());
+ }
+ valueBits.flip();
+ BigInteger resultValue = new BigInteger(+1, valueBits.array());
+ UperEncoder.logger.debug(String.format("big int Decoded as %s", resultValue));
+
+
+ //CG support for int range
+ if (intRange != null){
+ resultValue.add(BigInteger.valueOf(intRange.minValue()));
+ }
+
+
+ return UperEncoder.instantiate(classOfT, resultValue);
+ }
+
+ @Override public <T> boolean canEncode(T obj, Annotation[] extraAnnotations) {
+ return obj instanceof Asn1BigInteger;
+ }
+
+ @Override public <T> void encode(BitBuffer bitbuffer, T obj, Annotation[] extraAnnotations) throws Asn1EncodingException {
+ Class<?> type = obj.getClass();
+ AnnotationStore annotations = new AnnotationStore(type.getAnnotations(), extraAnnotations);
+ IntRange range = annotations.getAnnotation(IntRange.class);
+
+ //CG implementation with lower range limit added
+ BigInteger bint = ((Asn1BigInteger) obj).toBigInteger();
+ if (range != null) {
+ throw new UnsupportedOperationException("Asn1 BigInteger with range is not supported");
+ }
+ byte[] array = bint.toByteArray();
+ int lengthInOctets = array.length;
+ int position1 = bitbuffer.position();
+ try {
+ UperEncoder.encodeLengthDeterminant(bitbuffer, lengthInOctets);
+ } catch (Asn1EncodingException e) {
+ throw new Asn1EncodingException(" length determinant of " + type.getName(), e);
+ }
+ int position2 = bitbuffer.position();
+ for (byte b : array) {
+ bitbuffer.putByte(b);
+ }
+ UperEncoder.logger.debug(String.format("Big Int(%s): len %s, val %s", obj,
+ bitbuffer.toBooleanString(position1, position2 - position1),
+ bitbuffer.toBooleanStringFromPosition(position2)));
+ return;
+ }
+
+ @Override
+ public <T> T getDefault(Class<T> classOfT, Annotation[] extraAnnotations) {
+ AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(), extraAnnotations);
+ Asn1Default defaultAnnotation = annotations.getAnnotation(Asn1Default.class);
+ if (defaultAnnotation == null) return null;
+ //check whether the class has a constructor for numeric types
+ String valueString = defaultAnnotation.value();
+ long value = Long.parseLong(valueString);
+ UperEncoder.logger.debug(String.format("Default INTEGER: %d",value ));
+
+ @SuppressWarnings("unchecked")
+ T t = (T) new Asn1BigInteger(value);
+ return t;
+
+ }
+
+} \ No newline at end of file