001/*
002  GRANITE DATA SERVICES
003  Copyright (C) 2013 GRANITE DATA SERVICES S.A.S.
004
005  This file is part of Granite Data Services.
006
007  Granite Data Services is free software; you can redistribute it and/or modify
008  it under the terms of the GNU Library General Public License as published by
009  the Free Software Foundation; either version 2 of the License, or (at your
010  option) any later version.
011
012  Granite Data Services is distributed in the hope that it will be useful, but
013  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015  for more details.
016
017  You should have received a copy of the GNU Library General Public License
018  along with this library; if not, see <http://www.gnu.org/licenses/>.
019*/
020
021package org.granite.messaging.jmf.codec.std.impl;
022
023import java.io.IOException;
024import java.io.OutputStream;
025import java.math.BigInteger;
026
027import org.granite.messaging.jmf.DumpContext;
028import org.granite.messaging.jmf.InputContext;
029import org.granite.messaging.jmf.OutputContext;
030import org.granite.messaging.jmf.codec.std.BigIntegerCodec;
031
032/**
033 * @author Franck WOLFF
034 */
035public class BigIntegerCodecImpl extends AbstractIntegerStringCodec<BigInteger> implements BigIntegerCodec {
036
037        public int getObjectType() {
038                return JMF_BIG_INTEGER;
039        }
040
041        public Class<?> getObjectClass() {
042                return BigInteger.class;
043        }
044
045        public void encode(OutputContext ctx, BigInteger v) throws IOException {
046                final OutputStream os = ctx.getOutputStream();
047                
048                int indexOfStoredObject = ctx.indexOfStoredObjects(v);
049                if (indexOfStoredObject >= 0) {
050                        IntegerComponents ics = intComponents(indexOfStoredObject);
051                        os.write(0x80 | (ics.length << 5) | JMF_BIG_INTEGER);
052                        writeIntData(ctx, ics);
053                }
054                else {
055                        ctx.addToStoredObjects(v);
056                        
057                        byte[] magnitude = v.toByteArray();
058
059                        IntegerComponents ics = intComponents(magnitude.length);
060                        os.write((ics.length << 5) | JMF_BIG_INTEGER);
061                        writeIntData(ctx, ics);
062                        
063                        os.write(magnitude);
064                }
065        }
066
067        public BigInteger decode(InputContext ctx, int parameterizedJmfType) throws IOException {
068                int jmfType = ctx.getSharedContext().getCodecRegistry().extractJmfType(parameterizedJmfType);
069                
070                if (jmfType != JMF_BIG_INTEGER)
071                        throw newBadTypeJMFEncodingException(jmfType, parameterizedJmfType);
072                
073                int indexOrLength = readIntData(ctx, (parameterizedJmfType >> 5) & 0x03, false);
074                if ((parameterizedJmfType & 0x80) != 0)
075                        return (BigInteger)ctx.getSharedObject(indexOrLength);
076
077                byte[] magnitude = new byte[indexOrLength];
078                ctx.safeReadFully(magnitude);
079                BigInteger v = new BigInteger(magnitude);
080                
081                if (BigInteger.ZERO.equals(v))
082                        v = BigInteger.ZERO;
083                else if (BigInteger.ONE.equals(v))
084                        v = BigInteger.ONE;
085                else if (BigInteger.TEN.equals(v))
086                        v = BigInteger.TEN;
087                
088                return v;
089        }
090
091        public void dump(DumpContext ctx, int parameterizedJmfType) throws IOException {
092                int jmfType = ctx.getSharedContext().getCodecRegistry().extractJmfType(parameterizedJmfType);
093                if (jmfType != JMF_BIG_INTEGER)
094                        throw newBadTypeJMFEncodingException(jmfType, parameterizedJmfType);
095                ctx.indentPrintLn(BigInteger.class.getName() + ": " + decode(ctx, parameterizedJmfType));
096        }
097}