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.InputContext; 028import org.granite.messaging.jmf.OutputContext; 029 030/** 031 * @author Franck WOLFF 032 */ 033public abstract class AbstractIntegerStringCodec<T> extends AbstractStandardCodec<T> { 034 035 protected void writeIntData(OutputContext ctx, IntegerComponents ics) throws IOException { 036 int v = ics.value; 037 038 final OutputStream os = ctx.getOutputStream(); 039 040 switch (ics.length) { 041 case 3: 042 os.write(v >> 24); 043 case 2: 044 os.write(v >> 16); 045 case 1: 046 os.write(v >> 8); 047 case 0: 048 os.write(v); 049 break; 050 } 051 } 052 053 protected int readIntData(InputContext ctx, int length, boolean opposite) throws IOException { 054 int v = 0; 055 056 switch (length) { 057 case 3: 058 v |= ctx.safeRead() << 24; 059 case 2: 060 v |= ctx.safeRead() << 16; 061 case 1: 062 v |= ctx.safeRead() << 8; 063 case 0: 064 v |= ctx.safeRead(); 065 } 066 067 if (opposite) 068 v = -v; 069 070 return v; 071 } 072 073 protected IntegerComponents intComponents(int v) { 074 int s = 0; 075 int l = 3; // --> Integer.MIN_VALUE 076 if (v != Integer.MIN_VALUE) { 077 if (v < 0) { 078 s = 1; 079 v = -v; 080 } 081 if (v <= 0xFFFF) 082 l = (v <= 0xFF ? 0 : 1); 083 else 084 l = (v <= 0xFFFFFF ? 2 : 3); 085 } 086 return new IntegerComponents(s, l, v); 087 } 088 089 protected void writeString(OutputContext ctx, String v, StringTypeHandler handler) throws IOException { 090 if (v == null) 091 throw new NullPointerException("String value cannot be null"); 092 093 final OutputStream os = ctx.getOutputStream(); 094 095 int indexOfStoredString = ctx.indexOfStoredStrings(v); 096 097 if (indexOfStoredString >= 0) { 098 IntegerComponents ics = intComponents(indexOfStoredString); 099 os.write(handler.type(ics, true)); 100 writeIntData(ctx, ics); 101 } 102 else { 103 ctx.addToStoredStrings(v); 104 105 if (v.length() == 0) { 106 os.write(handler.type(IntegerComponents.ZERO, false)); 107 os.write(0); 108 } 109 else { 110 final byte[] bytes = v.getBytes(UTF8); 111 final int length = bytes.length; 112 113 IntegerComponents ics = intComponents(length); 114 os.write(handler.type(ics, false)); 115 writeIntData(ctx, ics); 116 117 os.write(bytes); 118 } 119 } 120 } 121 122 protected String readString(InputContext ctx, int parameterizedJmfType, StringTypeHandler handler) throws IOException { 123 int indexOrLength = readIntData(ctx, handler.indexOrLengthBytesCount(parameterizedJmfType), false); 124 return readString(ctx, parameterizedJmfType, indexOrLength, handler); 125 } 126 127 protected String readString(InputContext ctx, int parameterizedJmfType, int indexOrLength, StringTypeHandler handler) throws IOException { 128 if (handler.isReference(parameterizedJmfType)) 129 return ctx.getSharedString(indexOrLength); 130 131 byte[] bytes = new byte[indexOrLength]; 132 ctx.safeReadFully(bytes); 133 String s = new String(bytes, UTF8); 134 135 ctx.addSharedString(s); 136 137 return s; 138 } 139 140 protected static class IntegerComponents { 141 142 public static final IntegerComponents ZERO = new IntegerComponents(0, 0, 0); 143 144 public final int sign; 145 public final int length; 146 public final int value; 147 148 public IntegerComponents(int sign, int length, int value) { 149 this.sign = sign; 150 this.length = length; 151 this.value = value; 152 } 153 } 154 155 protected static interface StringTypeHandler { 156 157 int type(IntegerComponents ics, boolean reference); 158 int indexOrLengthBytesCount(int parameterizedJmfType); 159 boolean isReference(int parameterizedJmfType); 160 } 161 162 protected static final StringTypeHandler JMF_STRING_TYPE_HANDLER = new StringTypeHandler() { 163 164 public int type(IntegerComponents ics, boolean reference) { 165 if (reference) 166 return 0x80 | (ics.length << 5) | JMF_STRING; 167 return (ics.length << 5) | JMF_STRING; 168 } 169 170 public int indexOrLengthBytesCount(int parameterizedJmfType) { 171 return (parameterizedJmfType >> 5) & 0x03; 172 } 173 174 public boolean isReference(int parameterizedJmfType) { 175 return (parameterizedJmfType & 0x80) != 0; 176 } 177 }; 178}