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    
021    package org.granite.messaging.jmf.codec.std.impl;
022    
023    import java.io.IOException;
024    import java.io.OutputStream;
025    import java.math.BigInteger;
026    
027    import org.granite.messaging.jmf.DumpContext;
028    import org.granite.messaging.jmf.InputContext;
029    import org.granite.messaging.jmf.OutputContext;
030    import org.granite.messaging.jmf.codec.std.BigIntegerCodec;
031    
032    /**
033     * @author Franck WOLFF
034     */
035    public 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    }