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 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.io
;
15 import java
.nio
.BufferOverflowException
;
16 import java
.nio
.ByteBuffer
;
17 import java
.nio
.ByteOrder
;
20 * <b><u>BitBuffer</u></b>
22 * A bitwise buffer capable of accessing fields with bit offsets.
24 public class BitBuffer
{
26 // ------------------------------------------------------------------------
28 // ------------------------------------------------------------------------
30 /* default bit width */
31 /** 8 bits to a char */
32 public static final int BIT_CHAR
= 8;
33 /** 16 bits to a short */
34 public static final int BIT_SHORT
= 16;
35 /** 32 bits to an int */
36 public static final int BIT_INT
= 32;
37 /** 32 bits to a float */
38 public static final int BIT_FLOAT
= 32;
39 /** 64 bits to a long */
40 public static final int BIT_LONG
= 64;
42 // ------------------------------------------------------------------------
44 // ------------------------------------------------------------------------
46 private ByteBuffer buf
;
48 private ByteOrder byteOrder
;
50 // ------------------------------------------------------------------------
52 // ------------------------------------------------------------------------
54 * Default constructor, makes a bigendian buffer
57 this(null, ByteOrder
.BIG_ENDIAN
);
61 * Constructor, makes a bigendian buffer
64 * the bytebuffer to read
66 public BitBuffer(ByteBuffer buf
) {
67 this(buf
, ByteOrder
.BIG_ENDIAN
);
71 * Constructor that is fully parametrisable
76 * the byte order (big endian, little endian, network?)
78 public BitBuffer(ByteBuffer buf
, ByteOrder order
) {
84 // ------------------------------------------------------------------------
85 // 'Get' operations on buffer
86 // ------------------------------------------------------------------------
89 * Relative <i>get</i> method for reading 32-bit integer.
91 * Reads next four bytes from the current bit position according to current
94 * @return The int value read from the buffer
97 int val
= getInt(BIT_INT
, true);
103 * Relative <i>get</i> method for reading integer of <i>length</i> bits.
105 * Reads <i>length</i> bits starting at the current position. The result is
106 * signed extended if <i>signed</i> is true. The current position is
107 * increased of <i>length</i> bits.
110 * The length in bits of this integer
112 * The sign extended flag
113 * @return The int value read from the buffer
115 public int getInt(int length
, boolean signed
) {
117 if (!canRead(pos
, length
)) {
118 throw new BufferOverflowException();
123 if (byteOrder
== ByteOrder
.LITTLE_ENDIAN
) {
124 val
= getIntLE(pos
, length
, signed
);
126 val
= getIntBE(pos
, length
, signed
);
133 * Absolute <i>get</i> method for reading integer of <i>length</i> bits.
135 * Reads <i>length</i> bits starting from position <i>index</i>. The result
136 * is signed extended if <i>signed</i> is true. The current position is
137 * increased of <i>length</i> bits.
140 * The start index in bits
142 * The length in bits to read
144 * The sign extended flag
145 * @return The int value read from the buffer
147 public int getInt(int index
, int length
, boolean signed
) {
148 if (!canRead(index
, length
)) {
149 throw new BufferOverflowException();
154 if (byteOrder
== ByteOrder
.LITTLE_ENDIAN
) {
155 return getIntLE(index
, length
, signed
);
157 return getIntBE(index
, length
, signed
);
160 private int getIntBE(int index
, int length
, boolean signed
) {
161 assert ((length
> 0) && (length
<= BIT_INT
));
162 int end
= index
+ length
;
163 int startByte
= index
/ BIT_CHAR
;
164 int endByte
= (end
+ (BIT_CHAR
- 1)) / BIT_CHAR
;
165 int currByte
, lshift
, cshift
, mask
, cmask
, cache
;
168 currByte
= startByte
;
169 cache
= buf
.get(currByte
) & 0xFF;
170 boolean isNeg
= (cache
& (1 << (BIT_CHAR
- (index
% BIT_CHAR
) - 1))) != 0;
171 if (signed
&& isNeg
) {
174 if (startByte
== (endByte
- 1)) {
175 cmask
= cache
>>> ((BIT_CHAR
- (end
% BIT_CHAR
)) % BIT_CHAR
);
176 if (((length
) % BIT_CHAR
) > 0) {
177 mask
= ~
((~
0) << length
);
184 cshift
= index
% BIT_CHAR
;
186 mask
= ~
((~
0) << (BIT_CHAR
- cshift
));
187 cmask
= cache
& mask
;
188 lshift
= BIT_CHAR
- cshift
;
194 for (; currByte
< (endByte
- 1); currByte
++) {
196 value
|= buf
.get(currByte
) & 0xFF;
198 lshift
= end
% BIT_CHAR
;
200 mask
= ~
((~
0) << lshift
);
201 cmask
= buf
.get(currByte
) & 0xFF;
202 cmask
>>>= BIT_CHAR
- lshift
;
208 value
|= buf
.get(currByte
) & 0xFF;
213 private int getIntLE(int index
, int length
, boolean signed
) {
214 assert ((length
> 0) && (length
<= BIT_INT
));
215 int end
= index
+ length
;
216 int startByte
= index
/ BIT_CHAR
;
217 int endByte
= (end
+ (BIT_CHAR
- 1)) / BIT_CHAR
;
218 int currByte
, lshift
, cshift
, mask
, cmask
, cache
, mod
;
221 currByte
= endByte
- 1;
222 cache
= buf
.get(currByte
) & 0xFF;
223 mod
= end
% BIT_CHAR
;
224 lshift
= (mod
> 0) ? mod
: BIT_CHAR
;
225 boolean isNeg
= (cache
& (1 << (lshift
- 1))) != 0;
226 if (signed
&& isNeg
) {
229 if (startByte
== (endByte
- 1)) {
230 cmask
= cache
>>> (index
% BIT_CHAR
);
231 if (((length
) % BIT_CHAR
) > 0) {
232 mask
= ~
((~
0) << length
);
239 cshift
= end
% BIT_CHAR
;
241 mask
= ~
((~
0) << cshift
);
242 cmask
= cache
& mask
;
248 for (; currByte
>= (startByte
+ 1); currByte
--) {
250 value
|= buf
.get(currByte
) & 0xFF;
252 lshift
= index
% BIT_CHAR
;
254 mask
= ~
((~
0) << (BIT_CHAR
- lshift
));
255 cmask
= buf
.get(currByte
) & 0xFF;
258 value
<<= (BIT_CHAR
- lshift
);
262 value
|= buf
.get(currByte
) & 0xFF;
267 // ------------------------------------------------------------------------
268 // 'Put' operations on buffer
269 // ------------------------------------------------------------------------
272 * Relative <i>put</i> method to write signed 32-bit integer.
274 * Write four bytes starting from current bit position in the buffer
275 * according to the current byte order. The current position is increased of
276 * <i>length</i> bits.
279 * The int value to write
281 public void putInt(int value
) {
282 putInt(BIT_INT
, value
);
286 * Relative <i>put</i> method to write <i>length</i> bits integer.
288 * Writes <i>length</i> lower-order bits from the provided <i>value</i>,
289 * starting from current bit position in the buffer. Sequential bytes are
290 * written according to the current byte order. The sign bit is carried to
291 * the MSB if signed is true. The sign bit is included in <i>length</i>. The
292 * current position is increased of <i>length</i>.
295 * The number of bits to write
299 public void putInt(int length
, int value
) {
300 putInt(this.pos
, length
, value
);
304 * Absolute <i>put</i> method to write <i>length</i> bits integer.
306 * Writes <i>length</i> lower-order bits from the provided <i>value</i>,
307 * starting from <i>index</i> position in the buffer. Sequential bytes are
308 * written according to the current byte order. The sign bit is carried to
309 * the MSB if signed is true. The sign bit is included in <i>length</i>. The
310 * current position is increased of <i>length</i>.
313 * The start position to write the value
317 * The number of bits to write
319 public void putInt(int index
, int length
, int value
) {
320 if (!canRead(index
, length
)) {
321 throw new BufferOverflowException();
326 if (byteOrder
== ByteOrder
.LITTLE_ENDIAN
) {
327 putIntLE(index
, length
, value
);
329 putIntBE(index
, length
, value
);
333 private void putIntBE(int index
, int length
, int value
) {
334 assert ((length
> 0) && (length
<= BIT_INT
));
335 int end
= index
+ length
;
336 int startByte
= index
/ BIT_CHAR
;
337 int endByte
= (end
+ (BIT_CHAR
- 1)) / BIT_CHAR
;
338 int currByte
, lshift
, cshift
, mask
, cmask
;
339 int correctedValue
= value
;
342 * mask v high bits. Works for unsigned and two complement signed
343 * numbers which value do not overflow on length bits.
346 if (length
< BIT_INT
) {
347 correctedValue
&= ~
(~
0 << length
);
351 if (startByte
== (endByte
- 1)) {
352 lshift
= (BIT_CHAR
- (end
% BIT_CHAR
)) % BIT_CHAR
;
353 mask
= ~
((~
0) << lshift
);
354 if ((index
% BIT_CHAR
) > 0) {
355 mask
|= (~
(0)) << (BIT_CHAR
- (index
% BIT_CHAR
));
357 cmask
= correctedValue
<< lshift
;
359 * low bits are cleared because of lshift and high bits are already
363 int b
= buf
.get(startByte
) & 0xFF;
364 buf
.put(startByte
, (byte) ((b
& mask
) | cmask
));
368 /* head byte contains MSB */
369 currByte
= endByte
- 1;
370 cshift
= end
% BIT_CHAR
;
372 lshift
= BIT_CHAR
- cshift
;
373 mask
= ~
((~
0) << lshift
);
374 cmask
= correctedValue
<< lshift
;
376 int b
= buf
.get(currByte
) & 0xFF;
377 buf
.put(currByte
, (byte) ((b
& mask
) | cmask
));
378 correctedValue
>>>= cshift
;
384 for (; currByte
>= (startByte
+ 1); currByte
--) {
385 buf
.put(currByte
, (byte) correctedValue
);
386 correctedValue
>>>= BIT_CHAR
;
388 /* end byte contains LSB */
389 if ((index
% BIT_CHAR
) > 0) {
390 mask
= (~
0) << (BIT_CHAR
- (index
% BIT_CHAR
));
391 cmask
= correctedValue
& ~mask
;
392 int b
= buf
.get(currByte
) & 0xFF;
393 buf
.put(currByte
, (byte) ((b
& mask
) | cmask
));
395 buf
.put(currByte
, (byte) correctedValue
);
399 private void putIntLE(int index
, int length
, int value
) {
400 assert ((length
> 0) && (length
<= BIT_INT
));
401 int end
= index
+ length
;
402 int startByte
= index
/ BIT_CHAR
;
403 int endByte
= (end
+ (BIT_CHAR
- 1)) / BIT_CHAR
;
404 int currByte
, lshift
, cshift
, mask
, cmask
;
405 int correctedValue
= value
;
408 * mask v high bits. Works for unsigned and two complement signed
409 * numbers which value do not overflow on length bits.
412 if (length
< BIT_INT
) {
413 correctedValue
&= ~
(~
0 << length
);
417 if (startByte
== (endByte
- 1)) {
418 lshift
= index
% BIT_CHAR
;
419 mask
= ~
((~
0) << lshift
);
420 if ((end
% BIT_CHAR
) > 0) {
421 mask
|= (~
(0)) << (end
% BIT_CHAR
);
423 cmask
= correctedValue
<< lshift
;
425 * low bits are cleared because of lshift and high bits are already
429 int b
= buf
.get(startByte
) & 0xFF;
430 buf
.put(startByte
, (byte) ((b
& mask
) | cmask
));
435 currByte
= startByte
;
436 cshift
= index
% BIT_CHAR
;
438 mask
= ~
((~
0) << cshift
);
439 cmask
= correctedValue
<< cshift
;
441 int b
= buf
.get(currByte
) & 0xFF;
442 buf
.put(currByte
, (byte) ((b
& mask
) | cmask
));
443 correctedValue
>>>= BIT_CHAR
- cshift
;
444 // index += BIT_CHAR - cshift;
449 for (; currByte
< (endByte
- 1); currByte
++) {
450 buf
.put(currByte
, (byte) correctedValue
);
451 correctedValue
>>>= BIT_CHAR
;
454 if ((end
% BIT_CHAR
) > 0) {
455 mask
= (~
0) << (end
% BIT_CHAR
);
456 cmask
= correctedValue
& ~mask
;
457 int b
= buf
.get(currByte
) & 0xFF;
458 buf
.put(currByte
, (byte) ((b
& mask
) | cmask
));
460 buf
.put(currByte
, (byte) correctedValue
);
464 // ------------------------------------------------------------------------
465 // Buffer attributes handling
466 // ------------------------------------------------------------------------
469 * Can this buffer be read for thus amount of bits?
472 * the length in bits to read
473 * @return does the buffer have enough room to read the next "length"
475 public boolean canRead(int length
) {
476 return canRead(pos
, length
);
480 * Can this buffer be read for thus amount of bits?
483 * the position in the buffer to read
485 * the length in bits to read
486 * @return does the buffer have enough room to read the next "length"
488 public boolean canRead(int index
, int length
) {
493 if ((index
+ length
) > (buf
.capacity() * BIT_CHAR
)) {
500 * Sets the order of the buffer.
503 * The order of the buffer.
505 public void order(ByteOrder order
) {
506 this.byteOrder
= order
;
513 * Sets the order of the buffer.
515 * @return The order of the buffer.
517 public ByteOrder
order() {
522 * Sets the position in the buffer.
525 * The position of the buffer.
527 public void position(int newPosition
) {
528 this.pos
= newPosition
;
533 * Sets the position in the buffer.
535 * @return order The position of the buffer.
537 public int position() {
542 * Sets the byte buffer
547 public void setByteBuffer(ByteBuffer buf
) {
550 this.buf
.order(byteOrder
);
556 * Gets the byte buffer
558 * @return The byte buffer
560 public ByteBuffer
getByteBuffer() {
565 * Sets the byte order
570 public void setByteOrder(ByteOrder byteOrder
) {
571 this.byteOrder
= byteOrder
;
575 * Gets the byte order
577 * @return The byte order
579 public ByteOrder
getByteOrder() {
584 * resets the bitbuffer.
586 public void clear() {
This page took 0.043293 seconds and 6 git commands to generate.