BBEncoder.java
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((byteb);
117         }
118         catch (BufferOverflowException e)
119         {
120             grow(1);
121             out.put((byteb);
122         }
123     }
124 
125     public void writeUint16(int s)
126     {
127         assert s < 0x10000;
128 
129         try
130         {
131             out.putShort((shorts);
132         }
133         catch (BufferOverflowException e)
134         {
135             grow(2);
136             out.putShort((shorts);
137         }
138     }
139 
140     public void writeUint32(long i)
141     {
142         assert i < 0x100000000L;
143 
144         try
145         {
146             out.putInt((inti);
147         }
148         catch (BufferOverflowException e)
149         {
150             grow(4);
151             out.putInt((inti);
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((byte0);
174         }
175         catch (BufferOverflowException e)
176         {
177             grow(1);
178             out.put((byte0);
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((short0);
195         }
196         catch (BufferOverflowException e)
197         {
198             grow(2);
199             out.putShort((short0);
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 }