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