Improve javadoc for ctfAdapter in Tmf.Core
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / internal / ctf / core / event / io / BitBuffer.java
1 /*******************************************************************************.
2 * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
3 *
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
8 *
9 * Contributors: Matthew Khouzam - Initial Design and implementation
10 * Contributors: Francis Giraldeau - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.linuxtools.internal.ctf.core.event.io;
14
15 import java.nio.BufferOverflowException;
16 import java.nio.ByteBuffer;
17 import java.nio.ByteOrder;
18
19 /**
20 * <b><u>BitBuffer</u></b>
21 * <p>
22 * A bitwise buffer capable of accessing fields with bit offsets.
23 */
24 public class BitBuffer {
25
26 // ------------------------------------------------------------------------
27 // Constants
28 // ------------------------------------------------------------------------
29
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;
41
42 // ------------------------------------------------------------------------
43 // Attributes
44 // ------------------------------------------------------------------------
45
46 private ByteBuffer buf;
47 private int pos;
48 private ByteOrder byteOrder;
49
50 // ------------------------------------------------------------------------
51 // Constructors
52 // ------------------------------------------------------------------------
53 /**
54 * Default constructor, makes a bigendian buffer
55 */
56 public BitBuffer() {
57 this(null, ByteOrder.BIG_ENDIAN);
58 }
59
60 /**
61 * Constructor, makes a bigendian buffer
62 *
63 * @param buf
64 * the bytebuffer to read
65 */
66 public BitBuffer(ByteBuffer buf) {
67 this(buf, ByteOrder.BIG_ENDIAN);
68 }
69
70 /**
71 * Constructor that is fully parametrisable
72 *
73 * @param buf
74 * the buffer to read
75 * @param order
76 * the byte order (big endian, little endian, network?)
77 */
78 public BitBuffer(ByteBuffer buf, ByteOrder order) {
79 setByteBuffer(buf);
80 order(order);
81 position(0);
82 }
83
84 // ------------------------------------------------------------------------
85 // 'Get' operations on buffer
86 // ------------------------------------------------------------------------
87
88 /**
89 * Relative <i>get</i> method for reading 32-bit integer.
90 *
91 * Reads next four bytes from the current bit position according to current
92 * byte order.
93 *
94 * @return The int value read from the buffer
95 */
96 public int getInt() {
97 int val = getInt(BIT_INT, true);
98 pos += BIT_INT;
99 return val;
100 }
101
102 /**
103 * Relative <i>get</i> method for reading integer of <i>length</i> bits.
104 *
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.
108 *
109 * @param length
110 * The length in bits of this integer
111 * @param signed
112 * The sign extended flag
113 * @return The int value read from the buffer
114 */
115 public int getInt(int length, boolean signed) {
116 int val;
117 if (!canRead(pos, length)) {
118 throw new BufferOverflowException();
119 }
120 if (length == 0) {
121 val = 0;
122 }
123 if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
124 val = getIntLE(pos, length, signed);
125 } else {
126 val = getIntBE(pos, length, signed);
127 }
128 pos += length;
129 return val;
130 }
131
132 /**
133 * Absolute <i>get</i> method for reading integer of <i>length</i> bits.
134 *
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.
138 *
139 * @param index
140 * The start index in bits
141 * @param length
142 * The length in bits to read
143 * @param signed
144 * The sign extended flag
145 * @return The int value read from the buffer
146 */
147 public int getInt(int index, int length, boolean signed) {
148 if (!canRead(index, length)) {
149 throw new BufferOverflowException();
150 }
151 if (length == 0) {
152 return 0;
153 }
154 if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
155 return getIntLE(index, length, signed);
156 }
157 return getIntBE(index, length, signed);
158 }
159
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;
166 int value = 0;
167
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) {
172 value = ~0;
173 }
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);
178 cmask &= mask;
179 }
180 value <<= length;
181 value |= cmask;
182 return value;
183 }
184 cshift = index % BIT_CHAR;
185 if (cshift > 0) {
186 mask = ~((~0) << (BIT_CHAR - cshift));
187 cmask = cache & mask;
188 lshift = BIT_CHAR - cshift;
189 value <<= lshift;
190 value |= cmask;
191 // index += lshift;
192 currByte++;
193 }
194 for (; currByte < (endByte - 1); currByte++) {
195 value <<= BIT_CHAR;
196 value |= buf.get(currByte) & 0xFF;
197 }
198 lshift = end % BIT_CHAR;
199 if (lshift > 0) {
200 mask = ~((~0) << lshift);
201 cmask = buf.get(currByte) & 0xFF;
202 cmask >>>= BIT_CHAR - lshift;
203 cmask &= mask;
204 value <<= lshift;
205 value |= cmask;
206 } else {
207 value <<= BIT_CHAR;
208 value |= buf.get(currByte) & 0xFF;
209 }
210 return value;
211 }
212
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;
219 int value = 0;
220
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) {
227 value = ~0;
228 }
229 if (startByte == (endByte - 1)) {
230 cmask = cache >>> (index % BIT_CHAR);
231 if (((length) % BIT_CHAR) > 0) {
232 mask = ~((~0) << length);
233 cmask &= mask;
234 }
235 value <<= length;
236 value |= cmask;
237 return value;
238 }
239 cshift = end % BIT_CHAR;
240 if (cshift > 0) {
241 mask = ~((~0) << cshift);
242 cmask = cache & mask;
243 value <<= cshift;
244 value |= cmask;
245 // end -= cshift;
246 currByte--;
247 }
248 for (; currByte >= (startByte + 1); currByte--) {
249 value <<= BIT_CHAR;
250 value |= buf.get(currByte) & 0xFF;
251 }
252 lshift = index % BIT_CHAR;
253 if (lshift > 0) {
254 mask = ~((~0) << (BIT_CHAR - lshift));
255 cmask = buf.get(currByte) & 0xFF;
256 cmask >>>= lshift;
257 cmask &= mask;
258 value <<= (BIT_CHAR - lshift);
259 value |= cmask;
260 } else {
261 value <<= BIT_CHAR;
262 value |= buf.get(currByte) & 0xFF;
263 }
264 return value;
265 }
266
267 // ------------------------------------------------------------------------
268 // 'Put' operations on buffer
269 // ------------------------------------------------------------------------
270
271 /**
272 * Relative <i>put</i> method to write signed 32-bit integer.
273 *
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.
277 *
278 * @param value
279 * The int value to write
280 */
281 public void putInt(int value) {
282 putInt(BIT_INT, value);
283 }
284
285 /**
286 * Relative <i>put</i> method to write <i>length</i> bits integer.
287 *
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>.
293 *
294 * @param length
295 * The number of bits to write
296 * @param value
297 * The value to write
298 */
299 public void putInt(int length, int value) {
300 putInt(this.pos, length, value);
301 }
302
303 /**
304 * Absolute <i>put</i> method to write <i>length</i> bits integer.
305 *
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>.
311 *
312 * @param index
313 * The start position to write the value
314 * @param value
315 * The value to write
316 * @param length
317 * The number of bits to write
318 */
319 public void putInt(int index, int length, int value) {
320 if (!canRead(index, length)) {
321 throw new BufferOverflowException();
322 }
323 if (length == 0) {
324 return;
325 }
326 if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
327 putIntLE(index, length, value);
328 } else {
329 putIntBE(index, length, value);
330 }
331 }
332
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;
340
341 /*
342 * mask v high bits. Works for unsigned and two complement signed
343 * numbers which value do not overflow on length bits.
344 */
345
346 if (length < BIT_INT) {
347 correctedValue &= ~(~0 << length);
348 }
349
350 /* sub byte */
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));
356 }
357 cmask = correctedValue << lshift;
358 /*
359 * low bits are cleared because of lshift and high bits are already
360 * cleared
361 */
362 cmask &= ~mask;
363 int b = buf.get(startByte) & 0xFF;
364 buf.put(startByte, (byte) ((b & mask) | cmask));
365 return;
366 }
367
368 /* head byte contains MSB */
369 currByte = endByte - 1;
370 cshift = end % BIT_CHAR;
371 if (cshift > 0) {
372 lshift = BIT_CHAR - cshift;
373 mask = ~((~0) << lshift);
374 cmask = correctedValue << lshift;
375 cmask &= ~mask;
376 int b = buf.get(currByte) & 0xFF;
377 buf.put(currByte, (byte) ((b & mask) | cmask));
378 correctedValue >>>= cshift;
379 // end -= cshift;
380 currByte--;
381 }
382
383 /* middle byte(s) */
384 for (; currByte >= (startByte + 1); currByte--) {
385 buf.put(currByte, (byte) correctedValue);
386 correctedValue >>>= BIT_CHAR;
387 }
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));
394 } else {
395 buf.put(currByte, (byte) correctedValue);
396 }
397 }
398
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;
406
407 /*
408 * mask v high bits. Works for unsigned and two complement signed
409 * numbers which value do not overflow on length bits.
410 */
411
412 if (length < BIT_INT) {
413 correctedValue &= ~(~0 << length);
414 }
415
416 /* sub byte */
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);
422 }
423 cmask = correctedValue << lshift;
424 /*
425 * low bits are cleared because of lshift and high bits are already
426 * cleared
427 */
428 cmask &= ~mask;
429 int b = buf.get(startByte) & 0xFF;
430 buf.put(startByte, (byte) ((b & mask) | cmask));
431 return;
432 }
433
434 /* head byte */
435 currByte = startByte;
436 cshift = index % BIT_CHAR;
437 if (cshift > 0) {
438 mask = ~((~0) << cshift);
439 cmask = correctedValue << cshift;
440 cmask &= ~mask;
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;
445 currByte++;
446 }
447
448 /* middle byte(s) */
449 for (; currByte < (endByte - 1); currByte++) {
450 buf.put(currByte, (byte) correctedValue);
451 correctedValue >>>= BIT_CHAR;
452 }
453 /* end byte */
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));
459 } else {
460 buf.put(currByte, (byte) correctedValue);
461 }
462 }
463
464 // ------------------------------------------------------------------------
465 // Buffer attributes handling
466 // ------------------------------------------------------------------------
467
468 /**
469 * Can this buffer be read for thus amount of bits?
470 *
471 * @param length
472 * the length in bits to read
473 * @return does the buffer have enough room to read the next "length"
474 */
475 public boolean canRead(int length) {
476 return canRead(pos, length);
477 }
478
479 /**
480 * Can this buffer be read for thus amount of bits?
481 *
482 * @param index
483 * the position in the buffer to read
484 * @param length
485 * the length in bits to read
486 * @return does the buffer have enough room to read the next "length"
487 */
488 public boolean canRead(int index, int length) {
489 if (buf == null) {
490 return false;
491 }
492
493 if ((index + length) > (buf.capacity() * BIT_CHAR)) {
494 return false;
495 }
496 return true;
497 }
498
499 /**
500 * Sets the order of the buffer.
501 *
502 * @param order
503 * The order of the buffer.
504 */
505 public void order(ByteOrder order) {
506 this.byteOrder = order;
507 if (buf != null) {
508 buf.order(order);
509 }
510 }
511
512 /**
513 * Sets the order of the buffer.
514 *
515 * @return The order of the buffer.
516 */
517 public ByteOrder order() {
518 return byteOrder;
519 }
520
521 /**
522 * Sets the position in the buffer.
523 *
524 * @param order
525 * The position of the buffer.
526 */
527 public void position(int newPosition) {
528 this.pos = newPosition;
529 }
530
531 /**
532 *
533 * Sets the position in the buffer.
534 *
535 * @return order The position of the buffer.
536 */
537 public int position() {
538 return pos;
539 }
540
541 /**
542 * Sets the byte buffer
543 *
544 * @param buf
545 * the byte buffer
546 */
547 public void setByteBuffer(ByteBuffer buf) {
548 this.buf = buf;
549 if (buf != null) {
550 this.buf.order(byteOrder);
551 }
552 clear();
553 }
554
555 /**
556 * Gets the byte buffer
557 *
558 * @return The byte buffer
559 */
560 public ByteBuffer getByteBuffer() {
561 return buf;
562 }
563
564 /**
565 * Sets the byte order
566 *
567 * @param byteOrder
568 * The byte order
569 */
570 public void setByteOrder(ByteOrder byteOrder) {
571 this.byteOrder = byteOrder;
572 }
573
574 /**
575 * Gets the byte order
576 *
577 * @return The byte order
578 */
579 public ByteOrder getByteOrder() {
580 return byteOrder;
581 }
582
583 /**
584 * resets the bitbuffer.
585 */
586 public void clear() {
587 position(0);
588
589 if (buf == null) {
590 return;
591 }
592 buf.clear();
593 }
594
595 }
This page took 0.057189 seconds and 5 git commands to generate.