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 an Integer 026 * 027 */ 028 public class VarIntegerCodec implements Codec<Integer> { 029 030 public static final VarIntegerCodec INSTANCE = new VarIntegerCodec(); 031 032 public void encode(Integer x, DataOutput dataOut) throws IOException { 033 int value = x; 034 while (true) { 035 if ((value & ~0x7F) == 0) { 036 dataOut.writeByte(value); 037 return; 038 } else { 039 dataOut.writeByte((value & 0x7F) | 0x80); 040 value >>>= 7; 041 } 042 } 043 } 044 045 public Integer decode(DataInput dataIn) throws IOException { 046 byte tmp = dataIn.readByte(); 047 if (tmp >= 0) { 048 return (int)tmp; 049 } 050 int result = tmp & 0x7f; 051 if ((tmp = dataIn.readByte()) >= 0) { 052 result |= tmp << 7; 053 } else { 054 result |= (tmp & 0x7f) << 7; 055 if ((tmp = dataIn.readByte()) >= 0) { 056 result |= tmp << 14; 057 } else { 058 result |= (tmp & 0x7f) << 14; 059 if ((tmp = dataIn.readByte()) >= 0) { 060 result |= tmp << 21; 061 } else { 062 result |= (tmp & 0x7f) << 21; 063 result |= (tmp = dataIn.readByte()) << 28; 064 if (tmp < 0) { 065 // Discard upper 32 bits. 066 for (int i = 0; i < 5; i++) { 067 if (dataIn.readByte() >= 0) 068 return result; 069 } 070 throw new ProtocolException("Encountered a malformed variable int"); 071 } 072 } 073 } 074 } 075 return result; 076 } 077 078 public int getFixedSize() { 079 return -1; 080 } 081 082 /** 083 * @return the source object since integers are immutable. 084 */ 085 public Integer deepCopy(Integer source) { 086 return source; 087 } 088 089 public boolean isDeepCopySupported() { 090 return true; 091 } 092 093 public boolean isEstimatedSizeSupported() { 094 return true; 095 } 096 097 public int estimatedSize(Integer x) { 098 int value = x; 099 if ((value & (0xffffffff << 7)) == 0) 100 return 1; 101 if ((value & (0xffffffff << 14)) == 0) 102 return 2; 103 if ((value & (0xffffffff << 21)) == 0) 104 return 3; 105 if ((value & (0xffffffff << 28)) == 0) 106 return 4; 107 return 5; 108 } 109 }