001/** 002 * GRANITE DATA SERVICES 003 * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S. 004 * 005 * This file is part of the Granite Data Services Platform. 006 * 007 * Granite Data Services is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * Granite Data Services is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 015 * General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 020 * USA, or see <http://www.gnu.org/licenses/>. 021 */ 022package org.granite.messaging.jmf.codec.std.impl; 023 024import java.io.IOException; 025import java.io.OutputStream; 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.LongCodec; 031 032/** 033 * @author Franck WOLFF 034 */ 035public class LongCodecImpl extends AbstractStandardCodec<Long> implements LongCodec { 036 037 public int getObjectType() { 038 return JMF_LONG_OBJECT; 039 } 040 041 public Class<?> getObjectClass() { 042 return Long.class; 043 } 044 045 public int getPrimitiveType() { 046 return JMF_LONG; 047 } 048 049 public Class<?> getPrimitiveClass() { 050 return Long.TYPE; 051 } 052 053 public void encode(OutputContext ctx, Long v) throws IOException { 054 writeLongData(ctx, JMF_LONG_OBJECT, v.longValue()); 055 } 056 057 public Long decode(InputContext ctx, int parameterizedJmfType) throws IOException { 058 int jmfType = ctx.getSharedContext().getCodecRegistry().extractJmfType(parameterizedJmfType); 059 060 if (jmfType != JMF_LONG_OBJECT) 061 throw newBadTypeJMFEncodingException(jmfType, parameterizedJmfType); 062 063 return Long.valueOf(readLongData(ctx, parameterizedJmfType)); 064 } 065 066 public void encodePrimitive(OutputContext ctx, long v) throws IOException { 067 writeLongData(ctx, JMF_LONG, v); 068 } 069 070 public long decodePrimitive(InputContext ctx) throws IOException { 071 int parameterizedJmfType = ctx.safeRead(); 072 int jmfType = ctx.getSharedContext().getCodecRegistry().extractJmfType(parameterizedJmfType); 073 074 if (jmfType != JMF_LONG) 075 throw newBadTypeJMFEncodingException(jmfType, parameterizedJmfType); 076 077 return readLongData(ctx, parameterizedJmfType); 078 } 079 080 public void dump(DumpContext ctx, int parameterizedJmfType) throws IOException { 081 int jmfType = ctx.getSharedContext().getCodecRegistry().extractJmfType(parameterizedJmfType); 082 083 switch (jmfType) { 084 case JMF_LONG: 085 ctx.indentPrintLn("long: " + readLongData(ctx, parameterizedJmfType)); 086 break; 087 case JMF_LONG_OBJECT: 088 ctx.indentPrintLn(Long.class.getName() + ": " + Long.valueOf(readLongData(ctx, parameterizedJmfType))); 089 break; 090 default: 091 throw newBadTypeJMFEncodingException(jmfType, parameterizedJmfType); 092 } 093 } 094 095 protected void writeLongData(OutputContext ctx, int jmfType, long v) throws IOException { 096 int l = 7; // --> Long.MIN_VALUE 097 int s = 0x00; 098 if (v != Long.MIN_VALUE) { 099 if (v < 0) { 100 s = 0x80; 101 v = -v; 102 } 103 l = lenghtOfAbsoluteLong(v); 104 } 105 106 final OutputStream os = ctx.getOutputStream(); 107 108 os.write(s | (l << 4) | jmfType); 109 switch (l) { 110 case 7: 111 os.write((int)(v >> 56)); 112 case 6: 113 os.write((int)(v >> 48)); 114 case 5: 115 os.write((int)(v >> 40)); 116 case 4: 117 os.write((int)(v >> 32)); 118 case 3: 119 os.write((int)(v >> 24)); 120 case 2: 121 os.write((int)(v >> 16)); 122 case 1: 123 os.write((int)(v >> 8)); 124 case 0: 125 os.write((int)v); 126 break; 127 } 128 } 129 130 protected int lenghtOfAbsoluteLong(long v) { 131 if (v <= 0x00000000FFFFFFFFL) { 132 if (v <= 0x000000000000FFFFL) 133 return (v <= 0x00000000000000FFL ? 0 : 1); 134 return (v <= 0x0000000000FFFFFFL ? 2 : 3); 135 } 136 137 if (v <= 0x0000FFFFFFFFFFFFL) 138 return (v <= 0x000000FFFFFFFFFFL ? 4 : 5); 139 return (v <= 0x00FFFFFFFFFFFFFFL ? 6 : 7); 140 } 141 142 protected long readLongData(InputContext ctx, int parameterizedJmfType) throws IOException { 143 long v = 0; 144 145 switch ((parameterizedJmfType >> 4) & 0x07) { 146 case 7: 147 v |= ((long)ctx.safeRead()) << 56; 148 case 6: 149 v |= ((long)ctx.safeRead()) << 48; 150 case 5: 151 v |= ((long)ctx.safeRead()) << 40; 152 case 4: 153 v |= ((long)ctx.safeRead()) << 32; 154 case 3: 155 v |= ((long)ctx.safeRead()) << 24; 156 case 2: 157 v |= ((long)ctx.safeRead()) << 16; 158 case 1: 159 v |= ((long)ctx.safeRead()) << 8; 160 case 0: 161 v |= ctx.safeRead(); 162 } 163 164 if ((parameterizedJmfType & 0x80) != 0) 165 v = -v; 166 167 return v; 168 } 169 170 public void writeVariableLong(OutputContext ctx, long v) throws IOException { 171 172 final OutputStream os = ctx.getOutputStream(); 173 174 if (v == Long.MIN_VALUE) 175 os.write(0x80); 176 else { 177 int sign = 0x00; 178 if (v < 0) { 179 sign = 0x80; 180 v = -v; 181 } 182 183 int bytesCount = lengthOfVariableAbsoluteLong(v); 184 v -= deltaForVariableAbsoluteLongLength(bytesCount); 185 186 switch (bytesCount) { 187 case 0: 188 os.write(sign | (int)v); 189 break; 190 case 1: case 2: case 3: case 4: case 5: case 6: case 7: 191 os.write(sign | 0x40 | (int)(v >> (bytesCount * 7))); 192 for (int i = bytesCount - 1; i > 0; i--) 193 os.write(0x80 | (int)(v >> (i * 7))); 194 os.write(0x7F & (int)v); 195 break; 196 case 8: 197 os.write(sign | 0x40 | (int)(v >> 57)); 198 os.write(0x80 | (int)(v >> 50)); 199 os.write(0x80 | (int)(v >> 43)); 200 os.write(0x80 | (int)(v >> 36)); 201 os.write(0x80 | (int)(v >> 29)); 202 os.write(0x80 | (int)(v >> 22)); 203 os.write(0x80 | (int)(v >> 15)); 204 os.write(0x80 | (int)(v >> 8)); 205 os.write((int)v); 206 break; 207 } 208 } 209 } 210 211 public long readVariableLong(InputContext ctx) throws IOException { 212 long v = ctx.safeRead(); 213 214 if (v == 0x80L) 215 v = Long.MIN_VALUE; 216 else { 217 boolean opposite = ((v & 0x80L) != 0); 218 boolean readNext = (v & 0x40L) != 0; 219 220 v &= 0x3FL; 221 222 if (readNext) { 223 int l = 1; 224 for (int i = 1; i <= 7; i++) { 225 long u = ctx.safeRead(); 226 v = (v << 7) | (u & 0x7FL); 227 if ((u & 0x80L) == 0) { 228 readNext = false; 229 break; 230 } 231 l++; 232 } 233 if (readNext) 234 v = (v << 8) | ctx.safeRead(); 235 v += deltaForVariableAbsoluteLongLength(l); 236 } 237 238 if (opposite) 239 v = -v; 240 } 241 242 return v; 243 } 244 245 protected static final long[] VARIABLE_LONG_DELTAS = new long[9]; 246 static { 247 VARIABLE_LONG_DELTAS[0] = 0L; 248 for (int i = 1; i < VARIABLE_LONG_DELTAS.length; i++) 249 VARIABLE_LONG_DELTAS[i] = (VARIABLE_LONG_DELTAS[i-1] << 7) | 0x40L; 250 } 251 252 public int lengthOfVariableAbsoluteLong(long abs) { 253 for (int i = 1; i < VARIABLE_LONG_DELTAS.length; i++) { 254 if (abs < VARIABLE_LONG_DELTAS[i]) 255 return (i - 1); 256 } 257 return 8; 258 } 259 260 protected static long deltaForVariableAbsoluteLongLength(int len) { 261 return VARIABLE_LONG_DELTAS[len]; 262 } 263}