001 /*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements. See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership. The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied. See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 *
020 */
021 package org.apache.qpid.transport.codec;
022
023 import java.nio.BufferOverflowException;
024 import java.nio.ByteBuffer;
025 import java.nio.ByteOrder;
026
027
028 /**
029 * Byte Buffer Encoder.
030 * Encoder concrete implementor using a backing byte buffer for encoding data.
031 *
032 * @author Rafael H. Schloming
033 */
034 public final class BBEncoder extends AbstractEncoder
035 {
036 private ByteBuffer out;
037 private int segment;
038
039 public BBEncoder(int capacity) {
040 out = ByteBuffer.allocate(capacity);
041 out.order(ByteOrder.BIG_ENDIAN);
042 segment = 0;
043 }
044
045 public void init()
046 {
047 out.clear();
048 segment = 0;
049 }
050
051 public ByteBuffer segment()
052 {
053 int pos = out.position();
054 out.position(segment);
055 ByteBuffer slice = out.slice();
056 slice.limit(pos - segment);
057 out.position(pos);
058 segment = pos;
059 return slice;
060 }
061
062 private void grow(int size)
063 {
064 ByteBuffer old = out;
065 int capacity = old.capacity();
066 out = ByteBuffer.allocate(Math.max(capacity + size, 2*capacity));
067 out.order(ByteOrder.BIG_ENDIAN);
068 out.put(old);
069 }
070
071 protected void doPut(byte b)
072 {
073 try
074 {
075 out.put(b);
076 }
077 catch (BufferOverflowException e)
078 {
079 grow(1);
080 out.put(b);
081 }
082 }
083
084 protected void doPut(ByteBuffer src)
085 {
086 try
087 {
088 out.put(src);
089 }
090 catch (BufferOverflowException e)
091 {
092 grow(src.remaining());
093 out.put(src);
094 }
095 }
096
097 protected void put(byte[] bytes)
098 {
099 try
100 {
101 out.put(bytes);
102 }
103 catch (BufferOverflowException e)
104 {
105 grow(bytes.length);
106 out.put(bytes);
107 }
108 }
109
110 public void writeUint8(short b)
111 {
112 assert b < 0x100;
113
114 try
115 {
116 out.put((byte) b);
117 }
118 catch (BufferOverflowException e)
119 {
120 grow(1);
121 out.put((byte) b);
122 }
123 }
124
125 public void writeUint16(int s)
126 {
127 assert s < 0x10000;
128
129 try
130 {
131 out.putShort((short) s);
132 }
133 catch (BufferOverflowException e)
134 {
135 grow(2);
136 out.putShort((short) s);
137 }
138 }
139
140 public void writeUint32(long i)
141 {
142 assert i < 0x100000000L;
143
144 try
145 {
146 out.putInt((int) i);
147 }
148 catch (BufferOverflowException e)
149 {
150 grow(4);
151 out.putInt((int) i);
152 }
153 }
154
155 public void writeUint64(long l)
156 {
157 try
158 {
159 out.putLong(l);
160 }
161 catch (BufferOverflowException e)
162 {
163 grow(8);
164 out.putLong(l);
165 }
166 }
167
168 public int beginSize8()
169 {
170 int pos = out.position();
171 try
172 {
173 out.put((byte) 0);
174 }
175 catch (BufferOverflowException e)
176 {
177 grow(1);
178 out.put((byte) 0);
179 }
180 return pos;
181 }
182
183 public void endSize8(int pos)
184 {
185 int cur = out.position();
186 out.put(pos, (byte) (cur - pos - 1));
187 }
188
189 public int beginSize16()
190 {
191 int pos = out.position();
192 try
193 {
194 out.putShort((short) 0);
195 }
196 catch (BufferOverflowException e)
197 {
198 grow(2);
199 out.putShort((short) 0);
200 }
201 return pos;
202 }
203
204 public void endSize16(int pos)
205 {
206 int cur = out.position();
207 out.putShort(pos, (short) (cur - pos - 2));
208 }
209
210 public int beginSize32()
211 {
212 int pos = out.position();
213 try
214 {
215 out.putInt(0);
216 }
217 catch (BufferOverflowException e)
218 {
219 grow(4);
220 out.putInt(0);
221 }
222 return pos;
223 }
224
225 public void endSize32(int pos)
226 {
227 int cur = out.position();
228 out.putInt(pos, (cur - pos - 4));
229 }
230
231 public void writeDouble(double aDouble)
232 {
233 try
234 {
235 out.putDouble(aDouble);
236 } catch(BufferOverflowException exception)
237 {
238 grow(8);
239 out.putDouble(aDouble);
240 }
241 }
242
243 public void writeInt16(short aShort)
244 {
245 try
246 {
247 out.putShort(aShort);
248 } catch(BufferOverflowException exception)
249 {
250 grow(2);
251 out.putShort(aShort);
252 }
253 }
254
255 public void writeInt32(int anInt)
256 {
257 try
258 {
259 out.putInt(anInt);
260 } catch(BufferOverflowException exception)
261 {
262 grow(4);
263 out.putInt(anInt);
264 }
265 }
266
267 public void writeInt64(long aLong)
268 {
269 try
270 {
271 out.putLong(aLong);
272 } catch(BufferOverflowException exception)
273 {
274 grow(8);
275 out.putLong(aLong);
276 }
277 }
278
279 public void writeInt8(byte aByte)
280 {
281 try
282 {
283 out.put(aByte);
284 } catch(BufferOverflowException exception)
285 {
286 grow(1);
287 out.put(aByte);
288 }
289 }
290
291 public void writeBin128(byte[] byteArray)
292 {
293 byteArray = (byteArray != null) ? byteArray : new byte [16];
294
295 assert byteArray.length == 16;
296
297 try
298 {
299 out.put(byteArray);
300 } catch(BufferOverflowException exception)
301 {
302 grow(16);
303 out.put(byteArray);
304 }
305 }
306
307 public void writeFloat(float aFloat)
308 {
309 try
310 {
311 out.putFloat(aFloat);
312 } catch(BufferOverflowException exception)
313 {
314 grow(4);
315 out.putFloat(aFloat);
316 }
317 }
318
319 public void writeMagicNumber()
320 {
321 out.put("AM2".getBytes());
322 }
323 }
|