Work on TmfCheckpoint
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / 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.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 * TODO Implement me. Please.
23 */
24 public class BitBuffer {
25
26 // ------------------------------------------------------------------------
27 // Constants
28 // ------------------------------------------------------------------------
29
30 /* default bit width */
31 public static final int BIT_CHAR = 8;
32 public static final int BIT_SHORT = 16;
33 public static final int BIT_INT = 32;
34 public static final int BIT_FLOAT = 32;
35 public static final int BIT_LONG = 64;
36
37 // ------------------------------------------------------------------------
38 // Attributes
39 // ------------------------------------------------------------------------
40
41 private ByteBuffer buf;
42 private int pos;
43 private ByteOrder byteOrder;
44
45 // ------------------------------------------------------------------------
46 // Constructors
47 // ------------------------------------------------------------------------
48
49 public BitBuffer() {
50 this(null, ByteOrder.BIG_ENDIAN);
51 }
52
53 public BitBuffer(ByteBuffer buf) {
54 this(buf, ByteOrder.BIG_ENDIAN);
55 }
56
57 public BitBuffer(ByteBuffer buf, ByteOrder order) {
58 setByteBuffer(buf);
59 order(order);
60 position(0);
61 }
62
63 // ------------------------------------------------------------------------
64 // 'Get' operations on buffer
65 // ------------------------------------------------------------------------
66
67 /**
68 * Relative <i>get</i> method for reading 32-bit integer.
69 *
70 * Reads next four bytes from the current bit position according to current
71 * byte order.
72 *
73 * @return The int value read from the buffer
74 */
75 public int getInt() {
76 int val = getInt(BIT_INT, true);
77 pos += BIT_INT;
78 return val;
79 }
80
81 /**
82 * Relative <i>get</i> method for reading integer of <i>length</i> bits.
83 *
84 * Reads <i>length</i> bits starting at the current position. The result is
85 * signed extended if <i>signed</i> is true. The current position is
86 * increased of <i>length</i> bits.
87 *
88 * @param length
89 * The length in bits of this integer
90 * @param signed
91 * The sign extended flag
92 * @return The int value read from the buffer
93 */
94 public int getInt(int length, boolean signed) {
95 int val;
96 if (!canRead(pos, length)) {
97 throw new BufferOverflowException();
98 }
99 if (length == 0) {
100 val = 0;
101 }
102 if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
103 val = getIntLE(pos, length, signed);
104 } else {
105 val = getIntBE(pos, length, signed);
106 }
107 pos += length;
108 return val;
109 }
110
111 /**
112 * Absolute <i>get</i> method for reading integer of <i>length</i> bits.
113 *
114 * Reads <i>length</i> bits starting from position <i>index</i>. The result
115 * is signed extended if <i>signed</i> is true. The current position is
116 * increased of <i>length</i> bits.
117 *
118 * @param index
119 * The start index in bits
120 * @param length
121 * The length in bits to read
122 * @param signed
123 * The sign extended flag
124 * @return The int value read from the buffer
125 */
126 public int getInt(int index, int length, boolean signed) {
127 if (!canRead(index, length)) {
128 throw new BufferOverflowException();
129 }
130 if (length == 0) {
131 return 0;
132 }
133 if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
134 return getIntLE(index, length, signed);
135 }
136 return getIntBE(index, length, signed);
137 }
138
139 private int getIntBE(int index, int length, boolean signed) {
140 assert ((length > 0) && (length <= BIT_INT));
141 int end = index + length;
142 int startByte = index / BIT_CHAR;
143 int endByte = (end + (BIT_CHAR - 1)) / BIT_CHAR;
144 int currByte, lshift, cshift, mask, cmask, cache;
145 int value = 0;
146
147 currByte = startByte;
148 cache = buf.get(currByte) & 0xFF;
149 boolean isNeg = (cache & (1 << (BIT_CHAR - (index % BIT_CHAR) - 1))) != 0;
150 if (signed && isNeg) {
151 value = ~0;
152 }
153 if (startByte == (endByte - 1)) {
154 cmask = cache >>> ((BIT_CHAR - (end % BIT_CHAR)) % BIT_CHAR);
155 if (((length) % BIT_CHAR) > 0) {
156 mask = ~((~0) << length);
157 cmask &= mask;
158 }
159 value <<= length;
160 value |= cmask;
161 return value;
162 }
163 cshift = index % BIT_CHAR;
164 if (cshift > 0) {
165 mask = ~((~0) << (BIT_CHAR - cshift));
166 cmask = cache & mask;
167 lshift = BIT_CHAR - cshift;
168 value <<= lshift;
169 value |= cmask;
170 // index += lshift;
171 currByte++;
172 }
173 for (; currByte < (endByte - 1); currByte++) {
174 value <<= BIT_CHAR;
175 value |= buf.get(currByte) & 0xFF;
176 }
177 lshift = end % BIT_CHAR;
178 if (lshift > 0) {
179 mask = ~((~0) << lshift);
180 cmask = buf.get(currByte) & 0xFF;
181 cmask >>>= BIT_CHAR - lshift;
182 cmask &= mask;
183 value <<= lshift;
184 value |= cmask;
185 } else {
186 value <<= BIT_CHAR;
187 value |= buf.get(currByte) & 0xFF;
188 }
189 return value;
190 }
191
192 private int getIntLE(int index, int length, boolean signed) {
193 assert ((length > 0) && (length <= BIT_INT));
194 int end = index + length;
195 int startByte = index / BIT_CHAR;
196 int endByte = (end + (BIT_CHAR - 1)) / BIT_CHAR;
197 int currByte, lshift, cshift, mask, cmask, cache, mod;
198 int value = 0;
199
200 currByte = endByte - 1;
201 cache = buf.get(currByte) & 0xFF;
202 mod = end % BIT_CHAR;
203 lshift = (mod > 0) ? mod : BIT_CHAR;
204 boolean isNeg = (cache & (1 << (lshift - 1))) != 0;
205 if (signed && isNeg) {
206 value = ~0;
207 }
208 if (startByte == (endByte - 1)) {
209 cmask = cache >>> (index % BIT_CHAR);
210 if (((length) % BIT_CHAR) > 0) {
211 mask = ~((~0) << length);
212 cmask &= mask;
213 }
214 value <<= length;
215 value |= cmask;
216 return value;
217 }
218 cshift = end % BIT_CHAR;
219 if (cshift > 0) {
220 mask = ~((~0) << cshift);
221 cmask = cache & mask;
222 value <<= cshift;
223 value |= cmask;
224 // end -= cshift;
225 currByte--;
226 }
227 for (; currByte >= (startByte + 1); currByte--) {
228 value <<= BIT_CHAR;
229 value |= buf.get(currByte) & 0xFF;
230 }
231 lshift = index % BIT_CHAR;
232 if (lshift > 0) {
233 mask = ~((~0) << (BIT_CHAR - lshift));
234 cmask = buf.get(currByte) & 0xFF;
235 cmask >>>= lshift;
236 cmask &= mask;
237 value <<= (BIT_CHAR - lshift);
238 value |= cmask;
239 } else {
240 value <<= BIT_CHAR;
241 value |= buf.get(currByte) & 0xFF;
242 }
243 return value;
244 }
245
246 // ------------------------------------------------------------------------
247 // 'Put' operations on buffer
248 // ------------------------------------------------------------------------
249
250 /**
251 * Relative <i>put</i> method to write signed 32-bit integer.
252 *
253 * Write four bytes starting from current bit position in the buffer
254 * according to the current byte order. The current position is increased of
255 * <i>length</i> bits.
256 *
257 * @param value
258 * The int value to write
259 */
260 public void putInt(int value) {
261 putInt(BIT_INT, value);
262 }
263
264 /**
265 * Relative <i>put</i> method to write <i>length</i> bits integer.
266 *
267 * Writes <i>length</i> lower-order bits from the provided <i>value</i>,
268 * starting from current bit position in the buffer. Sequential bytes are
269 * written according to the current byte order. The sign bit is carried to
270 * the MSB if signed is true. The sign bit is included in <i>length</i>. The
271 * current position is increased of <i>length</i>.
272 *
273 * @param length
274 * The number of bits to write
275 * @param value
276 * The value to write
277 */
278 public void putInt(int length, int value) {
279 putInt(this.pos, length, value);
280 }
281
282 /**
283 * Absolute <i>put</i> method to write <i>length</i> bits integer.
284 *
285 * Writes <i>length</i> lower-order bits from the provided <i>value</i>,
286 * starting from <i>index</i> position in the buffer. Sequential bytes are
287 * written according to the current byte order. The sign bit is carried to
288 * the MSB if signed is true. The sign bit is included in <i>length</i>. The
289 * current position is increased of <i>length</i>.
290 *
291 * @param index
292 * The start position to write the value
293 * @param value
294 * The value to write
295 * @param length
296 * The number of bits to write
297 */
298 public void putInt(int index, int length, int value) {
299 if (!canRead(index, length)) {
300 throw new BufferOverflowException();
301 }
302 if (length == 0) {
303 return;
304 }
305 if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
306 putIntLE(index, length, value);
307 } else {
308 putIntBE(index, length, value);
309 }
310 }
311
312 private void putIntBE(int index, int length, int value) {
313 assert ((length > 0) && (length <= BIT_INT));
314 int end = index + length;
315 int startByte = index / BIT_CHAR;
316 int endByte = (end + (BIT_CHAR - 1)) / BIT_CHAR;
317 int currByte, lshift, cshift, mask, cmask;
318 int correctedValue = value;
319
320 /*
321 * mask v high bits. Works for unsigned and two complement signed
322 * numbers which value do not overflow on length bits.
323 */
324
325 if (length < BIT_INT) {
326 correctedValue &= ~(~0 << length);
327 }
328
329 /* sub byte */
330 if (startByte == (endByte - 1)) {
331 lshift = (BIT_CHAR - (end % BIT_CHAR)) % BIT_CHAR;
332 mask = ~((~0) << lshift);
333 if ((index % BIT_CHAR) > 0) {
334 mask |= (~(0)) << (BIT_CHAR - (index % BIT_CHAR));
335 }
336 cmask = correctedValue << lshift;
337 /*
338 * low bits are cleared because of lshift and high bits are already
339 * cleared
340 */
341 cmask &= ~mask;
342 int b = buf.get(startByte) & 0xFF;
343 buf.put(startByte, (byte) ((b & mask) | cmask));
344 return;
345 }
346
347 /* head byte contains MSB */
348 currByte = endByte - 1;
349 cshift = end % BIT_CHAR;
350 if (cshift > 0) {
351 lshift = BIT_CHAR - cshift;
352 mask = ~((~0) << lshift);
353 cmask = correctedValue << lshift;
354 cmask &= ~mask;
355 int b = buf.get(currByte) & 0xFF;
356 buf.put(currByte, (byte) ((b & mask) | cmask));
357 correctedValue >>>= cshift;
358 // end -= cshift;
359 currByte--;
360 }
361
362 /* middle byte(s) */
363 for (; currByte >= (startByte + 1); currByte--) {
364 buf.put(currByte, (byte) correctedValue);
365 correctedValue >>>= BIT_CHAR;
366 }
367 /* end byte contains LSB */
368 if ((index % BIT_CHAR) > 0) {
369 mask = (~0) << (BIT_CHAR - (index % BIT_CHAR));
370 cmask = correctedValue & ~mask;
371 int b = buf.get(currByte) & 0xFF;
372 buf.put(currByte, (byte) ((b & mask) | cmask));
373 } else {
374 buf.put(currByte, (byte) correctedValue);
375 }
376 }
377
378 private void putIntLE(int index, int length, int value) {
379 assert ((length > 0) && (length <= BIT_INT));
380 int end = index + length;
381 int startByte = index / BIT_CHAR;
382 int endByte = (end + (BIT_CHAR - 1)) / BIT_CHAR;
383 int currByte, lshift, cshift, mask, cmask;
384 int correctedValue = value;
385
386 /*
387 * mask v high bits. Works for unsigned and two complement signed
388 * numbers which value do not overflow on length bits.
389 */
390
391 if (length < BIT_INT) {
392 correctedValue &= ~(~0 << length);
393 }
394
395 /* sub byte */
396 if (startByte == (endByte - 1)) {
397 lshift = index % BIT_CHAR;
398 mask = ~((~0) << lshift);
399 if ((end % BIT_CHAR) > 0) {
400 mask |= (~(0)) << (end % BIT_CHAR);
401 }
402 cmask = correctedValue << lshift;
403 /*
404 * low bits are cleared because of lshift and high bits are already
405 * cleared
406 */
407 cmask &= ~mask;
408 int b = buf.get(startByte) & 0xFF;
409 buf.put(startByte, (byte) ((b & mask) | cmask));
410 return;
411 }
412
413 /* head byte */
414 currByte = startByte;
415 cshift = index % BIT_CHAR;
416 if (cshift > 0) {
417 mask = ~((~0) << cshift);
418 cmask = correctedValue << cshift;
419 cmask &= ~mask;
420 int b = buf.get(currByte) & 0xFF;
421 buf.put(currByte, (byte) ((b & mask) | cmask));
422 correctedValue >>>= BIT_CHAR - cshift;
423 // index += BIT_CHAR - cshift;
424 currByte++;
425 }
426
427 /* middle byte(s) */
428 for (; currByte < (endByte - 1); currByte++) {
429 buf.put(currByte, (byte) correctedValue);
430 correctedValue >>>= BIT_CHAR;
431 }
432 /* end byte */
433 if ((end % BIT_CHAR) > 0) {
434 mask = (~0) << (end % BIT_CHAR);
435 cmask = correctedValue & ~mask;
436 int b = buf.get(currByte) & 0xFF;
437 buf.put(currByte, (byte) ((b & mask) | cmask));
438 } else {
439 buf.put(currByte, (byte) correctedValue);
440 }
441 }
442
443 // ------------------------------------------------------------------------
444 // Buffer attributes handling
445 // ------------------------------------------------------------------------
446
447 public boolean canRead(int length) {
448 return canRead(pos, length);
449 }
450
451 public boolean canRead(int index, int length) {
452 if (buf == null) {
453 return false;
454 }
455
456 if ((index + length) > (buf.capacity() * BIT_CHAR)) {
457 return false;
458 }
459 return true;
460 }
461
462 public void order(ByteOrder order) {
463 this.byteOrder = order;
464 if (buf != null) {
465 buf.order(order);
466 }
467 }
468
469 public ByteOrder order() {
470 return byteOrder;
471 }
472
473 public void position(int newPosition) {
474 this.pos = newPosition;
475 }
476
477 public int position() {
478 return pos;
479 }
480
481 public void setByteBuffer(ByteBuffer buf) {
482 this.buf = buf;
483 if (buf != null) {
484 this.buf.order(byteOrder);
485 }
486 clear();
487 }
488
489 public ByteBuffer getByteBuffer() {
490 return buf;
491 }
492
493 public void setByteOrder(ByteOrder byteOrder) {
494 this.byteOrder = byteOrder;
495 }
496
497 public ByteOrder getByteOrder() {
498 return byteOrder;
499 }
500
501 public void clear() {
502 position(0);
503
504 if (buf == null) {
505 return;
506 }
507 buf.clear();
508 }
509
510 }
This page took 0.058751 seconds and 5 git commands to generate.