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 */
022 package org.granite.messaging.jmf.codec.std.impl;
023
024 import java.io.IOException;
025 import java.io.OutputStream;
026
027 import org.granite.messaging.jmf.InputContext;
028 import org.granite.messaging.jmf.OutputContext;
029
030 /**
031 * @author Franck WOLFF
032 */
033 public 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 }