001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.fusesource.hawtbuf.codec;
018    
019    import java.io.DataInput;
020    import java.io.DataOutput;
021    import java.io.IOException;
022    import java.net.ProtocolException;
023    
024    /**
025     * Implementation of a variable length Codec for a Long
026     *
027     */
028    public class VarLongCodec implements Codec<Long> {
029    
030        public static final VarLongCodec INSTANCE = new VarLongCodec();
031    
032        public void encode(Long object, DataOutput dataOut) throws IOException {
033            long value = object;
034            while (true) {
035                if ((value & ~0x7FL) == 0) {
036                    dataOut.writeByte((int) value);
037                    return;
038                } else {
039                    dataOut.writeByte(((int) value & 0x7F) | 0x80);
040                    value >>>= 7;
041                }
042            }
043        }
044    
045        public Long decode(DataInput dataIn) throws IOException {
046            int shift = 0;
047            long result = 0;
048            while (shift < 64) {
049                byte b = dataIn.readByte();
050                result |= (long) (b & 0x7F) << shift;
051                if ((b & 0x80) == 0)
052                    return result;
053                shift += 7;
054            }
055            throw new ProtocolException("Encountered a malformed variable int");
056        }
057    
058        public boolean isEstimatedSizeSupported() {
059            return true;
060        }
061    
062        public int estimatedSize(Long object) {
063            long value = object;
064            if ((value & (0xffffffffffffffffL << 7)) == 0)
065                return 1;
066            if ((value & (0xffffffffffffffffL << 14)) == 0)
067                return 2;
068            if ((value & (0xffffffffffffffffL << 21)) == 0)
069                return 3;
070            if ((value & (0xffffffffffffffffL << 28)) == 0)
071                return 4;
072            if ((value & (0xffffffffffffffffL << 35)) == 0)
073                return 5;
074            if ((value & (0xffffffffffffffffL << 42)) == 0)
075                return 6;
076            if ((value & (0xffffffffffffffffL << 49)) == 0)
077                return 7;
078            if ((value & (0xffffffffffffffffL << 56)) == 0)
079                return 8;
080            if ((value & (0xffffffffffffffffL << 63)) == 0)
081                return 9;
082            return 10;
083        }
084    
085        public int getFixedSize() {
086            return -1;
087        }
088    
089        public Long deepCopy(Long source) {
090            return source;
091        }
092    
093        public boolean isDeepCopySupported() {
094            return true;
095        }
096    
097    }