1 /*******************************************************************************.
2 * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
9 * Contributors: Matthew Khouzam - Initial Design and implementation
10 * Contributors: Francis Giraldeau - Initial API and implementation
11 * Contributors: Philippe Proulx - Some refinement and optimization
12 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.ctf
.core
.event
.io
;
16 import java
.nio
.BufferOverflowException
;
17 import java
.nio
.ByteBuffer
;
18 import java
.nio
.ByteOrder
;
21 * <b><u>BitBuffer</u></b>
23 * A bitwise buffer capable of accessing fields with bit offsets.
26 public class BitBuffer
{
28 // ------------------------------------------------------------------------
30 // ------------------------------------------------------------------------
32 /* default bit width */
33 /** 8 bits to a char */
34 public static final int BIT_CHAR
= 8;
35 /** 16 bits to a short */
36 public static final int BIT_SHORT
= 16;
37 /** 32 bits to an int */
38 public static final int BIT_INT
= 32;
39 /** 32 bits to a float */
40 public static final int BIT_FLOAT
= 32;
41 /** 64 bits to a long */
42 public static final int BIT_LONG
= 64;
44 // ------------------------------------------------------------------------
46 // ------------------------------------------------------------------------
48 private ByteBuffer buf
;
50 private ByteOrder byteOrder
;
52 // ------------------------------------------------------------------------
54 // ------------------------------------------------------------------------
56 * Default constructor, makes a bigendian buffer
59 this(null, ByteOrder
.BIG_ENDIAN
);
63 * Constructor, makes a bigendian buffer
66 * the bytebuffer to read
68 public BitBuffer(ByteBuffer buf
) {
69 this(buf
, ByteOrder
.BIG_ENDIAN
);
73 * Constructor that is fully parametrisable
78 * the byte order (big endian, little endian, network?)
80 public BitBuffer(ByteBuffer buf
, ByteOrder order
) {
86 // ------------------------------------------------------------------------
87 // 'Get' operations on buffer
88 // ------------------------------------------------------------------------
91 * Relative <i>get</i> method for reading 32-bit integer.
93 * Reads next four bytes from the current bit position according to current
96 * @return The int value read from the buffer
99 int val
= getInt(BIT_INT
, true);
104 * Relative <i>get</i> method for reading integer of <i>length</i> bits.
106 * Reads <i>length</i> bits starting at the current position. The result is
107 * signed extended if <i>signed</i> is true. The current position is
108 * increased of <i>length</i> bits.
111 * The length in bits of this integer
113 * The sign extended flag
114 * @return The int value read from the buffer
116 public int getInt(int length
, boolean signed
) {
118 if (!canRead(length
)) {
119 throw new BufferOverflowException();
124 boolean gotIt
= false;
126 // Fall back to fast ByteBuffer reader if we want to read byte-aligned bytes
127 if (this.pos
% BitBuffer
.BIT_CHAR
== 0) {
129 case BitBuffer
.BIT_CHAR
:
132 val
= this.buf
.get(this.pos
/ 8);
134 val
= (this.buf
.get(this.pos
/ 8)) & 0xff;
139 case BitBuffer
.BIT_SHORT
:
142 val
= this.buf
.getShort(this.pos
/ 8);
144 short a
= this.buf
.getShort(this.pos
/ 8);
150 case BitBuffer
.BIT_INT
:
152 val
= this.buf
.getInt(this.pos
/ 8);
161 // Nothing read yet: use longer methods
162 if (this.byteOrder
== ByteOrder
.LITTLE_ENDIAN
) {
163 val
= getIntLE(this.pos
, length
, signed
);
165 val
= getIntBE(this.pos
, length
, signed
);
173 private int getIntBE(int index
, int length
, boolean signed
) {
174 assert ((length
> 0) && (length
<= BIT_INT
));
175 int end
= index
+ length
;
176 int startByte
= index
/ BIT_CHAR
;
177 int endByte
= (end
+ (BIT_CHAR
- 1)) / BIT_CHAR
;
178 int currByte
, lshift
, cshift
, mask
, cmask
, cache
;
181 currByte
= startByte
;
182 cache
= this.buf
.get(currByte
) & 0xFF;
183 boolean isNeg
= (cache
& (1 << (BIT_CHAR
- (index
% BIT_CHAR
) - 1))) != 0;
184 if (signed
&& isNeg
) {
187 if (startByte
== (endByte
- 1)) {
188 cmask
= cache
>>> ((BIT_CHAR
- (end
% BIT_CHAR
)) % BIT_CHAR
);
189 if (((length
) % BIT_CHAR
) > 0) {
190 mask
= ~
((~
0) << length
);
197 cshift
= index
% BIT_CHAR
;
199 mask
= ~
((~
0) << (BIT_CHAR
- cshift
));
200 cmask
= cache
& mask
;
201 lshift
= BIT_CHAR
- cshift
;
207 for (; currByte
< (endByte
- 1); currByte
++) {
209 value
|= this.buf
.get(currByte
) & 0xFF;
211 lshift
= end
% BIT_CHAR
;
213 mask
= ~
((~
0) << lshift
);
214 cmask
= this.buf
.get(currByte
) & 0xFF;
215 cmask
>>>= BIT_CHAR
- lshift
;
221 value
|= this.buf
.get(currByte
) & 0xFF;
226 private int getIntLE(int index
, int length
, boolean signed
) {
227 assert ((length
> 0) && (length
<= BIT_INT
));
228 int end
= index
+ length
;
229 int startByte
= index
/ BIT_CHAR
;
230 int endByte
= (end
+ (BIT_CHAR
- 1)) / BIT_CHAR
;
231 int currByte
, lshift
, cshift
, mask
, cmask
, cache
, mod
;
234 currByte
= endByte
- 1;
235 cache
= buf
.get(currByte
) & 0xFF;
236 mod
= end
% BIT_CHAR
;
237 lshift
= (mod
> 0) ? mod
: BIT_CHAR
;
238 boolean isNeg
= (cache
& (1 << (lshift
- 1))) != 0;
239 if (signed
&& isNeg
) {
242 if (startByte
== (endByte
- 1)) {
243 cmask
= cache
>>> (index
% BIT_CHAR
);
244 if (((length
) % BIT_CHAR
) > 0) {
245 mask
= ~
((~
0) << length
);
252 cshift
= end
% BIT_CHAR
;
254 mask
= ~
((~
0) << cshift
);
255 cmask
= cache
& mask
;
261 for (; currByte
>= (startByte
+ 1); currByte
--) {
263 value
|= buf
.get(currByte
) & 0xFF;
265 lshift
= index
% BIT_CHAR
;
267 mask
= ~
((~
0) << (BIT_CHAR
- lshift
));
268 cmask
= buf
.get(currByte
) & 0xFF;
271 value
<<= (BIT_CHAR
- lshift
);
275 value
|= buf
.get(currByte
) & 0xFF;
280 // ------------------------------------------------------------------------
281 // 'Put' operations on buffer
282 // ------------------------------------------------------------------------
285 * Relative <i>put</i> method to write signed 32-bit integer.
287 * Write four bytes starting from current bit position in the buffer
288 * according to the current byte order. The current position is increased of
289 * <i>length</i> bits.
292 * The int value to write
294 public void putInt(int value
) {
295 putInt(BIT_INT
, value
);
299 * Relative <i>put</i> method to write <i>length</i> bits integer.
301 * Writes <i>length</i> lower-order bits from the provided <i>value</i>,
302 * starting from current bit position in the buffer. Sequential bytes are
303 * written according to the current byte order. The sign bit is carried to
304 * the MSB if signed is true. The sign bit is included in <i>length</i>. The
305 * current position is increased of <i>length</i>.
308 * The number of bits to write
312 public void putInt(int length
, int value
) {
313 final int curPos
= this.pos
;
315 if (!canRead(length
)) {
316 throw new BufferOverflowException();
321 if (this.byteOrder
== ByteOrder
.LITTLE_ENDIAN
) {
322 putIntLE(curPos
, length
, value
);
324 putIntBE(curPos
, length
, value
);
329 private void putIntBE(int index
, int length
, int value
) {
330 assert ((length
> 0) && (length
<= BIT_INT
));
331 int end
= index
+ length
;
332 int startByte
= index
/ BIT_CHAR
;
333 int endByte
= (end
+ (BIT_CHAR
- 1)) / BIT_CHAR
;
334 int currByte
, lshift
, cshift
, mask
, cmask
;
335 int correctedValue
= value
;
338 * mask v high bits. Works for unsigned and two complement signed
339 * numbers which value do not overflow on length bits.
342 if (length
< BIT_INT
) {
343 correctedValue
&= ~
(~
0 << length
);
347 if (startByte
== (endByte
- 1)) {
348 lshift
= (BIT_CHAR
- (end
% BIT_CHAR
)) % BIT_CHAR
;
349 mask
= ~
((~
0) << lshift
);
350 if ((index
% BIT_CHAR
) > 0) {
351 mask
|= (~
(0)) << (BIT_CHAR
- (index
% BIT_CHAR
));
353 cmask
= correctedValue
<< lshift
;
355 * low bits are cleared because of lshift and high bits are already
359 int b
= this.buf
.get(startByte
) & 0xFF;
360 this.buf
.put(startByte
, (byte) ((b
& mask
) | cmask
));
364 /* head byte contains MSB */
365 currByte
= endByte
- 1;
366 cshift
= end
% BIT_CHAR
;
368 lshift
= BIT_CHAR
- cshift
;
369 mask
= ~
((~
0) << lshift
);
370 cmask
= correctedValue
<< lshift
;
372 int b
= this.buf
.get(currByte
) & 0xFF;
373 this.buf
.put(currByte
, (byte) ((b
& mask
) | cmask
));
374 correctedValue
>>>= cshift
;
380 for (; currByte
>= (startByte
+ 1); currByte
--) {
381 this.buf
.put(currByte
, (byte) correctedValue
);
382 correctedValue
>>>= BIT_CHAR
;
384 /* end byte contains LSB */
385 if ((index
% BIT_CHAR
) > 0) {
386 mask
= (~
0) << (BIT_CHAR
- (index
% BIT_CHAR
));
387 cmask
= correctedValue
& ~mask
;
388 int b
= this.buf
.get(currByte
) & 0xFF;
389 this.buf
.put(currByte
, (byte) ((b
& mask
) | cmask
));
391 this.buf
.put(currByte
, (byte) correctedValue
);
395 private void putIntLE(int index
, int length
, int value
) {
396 assert ((length
> 0) && (length
<= BIT_INT
));
397 int end
= index
+ length
;
398 int startByte
= index
/ BIT_CHAR
;
399 int endByte
= (end
+ (BIT_CHAR
- 1)) / BIT_CHAR
;
400 int currByte
, lshift
, cshift
, mask
, cmask
;
401 int correctedValue
= value
;
404 * mask v high bits. Works for unsigned and two complement signed
405 * numbers which value do not overflow on length bits.
408 if (length
< BIT_INT
) {
409 correctedValue
&= ~
(~
0 << length
);
413 if (startByte
== (endByte
- 1)) {
414 lshift
= index
% BIT_CHAR
;
415 mask
= ~
((~
0) << lshift
);
416 if ((end
% BIT_CHAR
) > 0) {
417 mask
|= (~
(0)) << (end
% BIT_CHAR
);
419 cmask
= correctedValue
<< lshift
;
421 * low bits are cleared because of lshift and high bits are already
425 int b
= this.buf
.get(startByte
) & 0xFF;
426 this.buf
.put(startByte
, (byte) ((b
& mask
) | cmask
));
431 currByte
= startByte
;
432 cshift
= index
% BIT_CHAR
;
434 mask
= ~
((~
0) << cshift
);
435 cmask
= correctedValue
<< cshift
;
437 int b
= this.buf
.get(currByte
) & 0xFF;
438 this.buf
.put(currByte
, (byte) ((b
& mask
) | cmask
));
439 correctedValue
>>>= BIT_CHAR
- cshift
;
440 // index += BIT_CHAR - cshift;
445 for (; currByte
< (endByte
- 1); currByte
++) {
446 this.buf
.put(currByte
, (byte) correctedValue
);
447 correctedValue
>>>= BIT_CHAR
;
450 if ((end
% BIT_CHAR
) > 0) {
451 mask
= (~
0) << (end
% BIT_CHAR
);
452 cmask
= correctedValue
& ~mask
;
453 int b
= this.buf
.get(currByte
) & 0xFF;
454 this.buf
.put(currByte
, (byte) ((b
& mask
) | cmask
));
456 this.buf
.put(currByte
, (byte) correctedValue
);
460 // ------------------------------------------------------------------------
461 // Buffer attributes handling
462 // ------------------------------------------------------------------------
465 * Can this buffer be read for thus amount of bits?
468 * the length in bits to read
469 * @return does the buffer have enough room to read the next "length"
471 public boolean canRead(int length
) {
472 if (this.buf
== null) {
476 if ((this.pos
+ length
) > (this.buf
.capacity() * BIT_CHAR
)) {
483 * Sets the order of the buffer.
486 * The order of the buffer.
488 public void setByteOrder(ByteOrder order
) {
489 this.byteOrder
= order
;
490 if (this.buf
!= null) {
491 this.buf
.order(order
);
496 * Sets the order of the buffer.
498 * @return The order of the buffer.
500 public ByteOrder
getByteOrder() {
501 return this.byteOrder
;
505 * Sets the position in the buffer.
508 * The new position of the buffer.
510 public void position(int newPosition
) {
511 this.pos
= newPosition
;
516 * Sets the position in the buffer.
518 * @return order The position of the buffer.
520 public int position() {
525 * Sets the byte buffer
530 public void setByteBuffer(ByteBuffer buf
) {
533 this.buf
.order(this.byteOrder
);
539 * Gets the byte buffer
541 * @return The byte buffer
543 public ByteBuffer
getByteBuffer() {
548 * resets the bitbuffer.
550 public void clear() {
553 if (this.buf
== null) {
This page took 0.060468 seconds and 5 git commands to generate.