Make sure invokeOperation is set once
[controller.git] / opendaylight / adsal / sal / api / src / main / java / org / opendaylight / controller / sal / packet / BitBufferHelper.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 /**
10  *
11  */
12 package org.opendaylight.controller.sal.packet;
13
14 import java.util.Arrays;
15
16 import org.opendaylight.controller.sal.utils.NetUtils;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20 /**
21  * BitBufferHelper class that provides utility methods to
22  * - fetch specific bits from a serialized stream of bits
23  * - convert bits to primitive data type - like short, int, long
24  * - store bits in specified location in stream of bits
25  * - convert primitive data types to stream of bits
26  */
27 @Deprecated
28 public abstract class BitBufferHelper {
29     protected static final Logger logger = LoggerFactory
30     .getLogger(BitBufferHelper.class);
31
32     public static final long ByteMask = 0xFF;
33
34     // Getters
35     // data: array where data are stored
36     // startOffset: bit from where to start reading
37     // numBits: number of bits to read
38     // All this function return an exception if overflow or underflow
39
40     /**
41      * Returns the first byte from the byte array
42      * @param byte[] data
43      * @return byte value
44      */
45     public static byte getByte(byte[] data) {
46         if ((data.length * NetUtils.NumBitsInAByte) > Byte.SIZE) {
47             try {
48                 throw new BufferException(
49                         "Container is too small for the number of requested bits");
50             } catch (BufferException e) {
51                 logger.error("", e);
52             }
53         }
54         return (data[0]);
55     }
56
57     /**
58      * Returns the short value for the byte array passed.
59      * Size of byte array is restricted to Short.SIZE
60      * @param byte[] data
61      * @return short value
62      */
63     public static short getShort(byte[] data) {
64         if (data.length > Short.SIZE) {
65             try {
66                 throw new BufferException(
67                         "Container is too small for the number of requested bits");
68             } catch (BufferException e) {
69                 logger.error("", e);
70             }
71         }
72         return (short) toNumber(data);
73     }
74
75     /**
76      * Returns the int value for the byte array passed.
77      * Size of byte array is restricted to Integer.SIZE
78      * @param byte[] data
79      * @return int - the integer value of byte array
80      */
81     public static int getInt(byte[] data) {
82         if (data.length > Integer.SIZE) {
83             try {
84                 throw new BufferException(
85                         "Container is too small for the number of requested bits");
86             } catch (BufferException e) {
87                 logger.error("", e);
88             }
89         }
90         return (int) toNumber(data);
91     }
92
93     /**
94      * Returns the long value for the byte array passed.
95      * Size of byte array is restricted to Long.SIZE
96      * @param byte[] data
97      * @return long - the integer value of byte array
98      */
99     public static long getLong(byte[] data) {
100         if (data.length > Long.SIZE) {
101             try {
102                 throw new BufferException(
103                         "Container is too small for the number of requested bits");
104             } catch (Exception e) {
105                 logger.error("", e);
106             }
107         }
108         return (long) toNumber(data);
109     }
110
111     /**
112      * Returns the short value for the last numBits of the byte array passed.
113      * Size of numBits is restricted to Short.SIZE
114      * @param byte[] data
115      * @param int - numBits
116      * @return short - the short value of byte array
117      */
118     public static short getShort(byte[] data, int numBits) {
119         if (numBits > Short.SIZE) {
120             try {
121                 throw new BufferException(
122                         "Container is too small for the number of requested bits");
123             } catch (BufferException e) {
124                 logger.error("", e);
125             }
126         }
127         int startOffset = data.length * NetUtils.NumBitsInAByte - numBits;
128         byte[] bits = null;
129         try {
130             bits = BitBufferHelper.getBits(data, startOffset, numBits);
131         } catch (BufferException e) {
132             logger.error("", e);
133         }
134         return (short) toNumber(bits, numBits);
135     }
136
137     /**
138      * Returns the int value for the last numBits of the byte array passed.
139      * Size of numBits is restricted to Integer.SIZE
140      * @param byte[] data
141      * @param int - numBits
142      * @return int - the integer value of byte array
143      */
144     public static int getInt(byte[] data, int numBits) {
145         if (numBits > Integer.SIZE) {
146             try {
147                 throw new BufferException(
148                         "Container is too small for the number of requested bits");
149             } catch (BufferException e) {
150                 logger.error("", e);
151             }
152         }
153         int startOffset = data.length * NetUtils.NumBitsInAByte - numBits;
154         byte[] bits = null;
155         try {
156             bits = BitBufferHelper.getBits(data, startOffset, numBits);
157         } catch (BufferException e) {
158             logger.error("", e);
159         }
160         return (int) toNumber(bits, numBits);
161     }
162
163     /**
164      * Returns the long value for the last numBits of the byte array passed.
165      * Size of numBits is restricted to Long.SIZE
166      * @param byte[] data
167      * @param int - numBits
168      * @return long - the integer value of byte array
169      */
170     public static long getLong(byte[] data, int numBits) {
171         if (numBits > Long.SIZE) {
172             try {
173                 throw new BufferException(
174                         "Container is too small for the number of requested bits");
175             } catch (BufferException e) {
176                 logger.error("", e);
177             }
178         }
179         if (numBits > data.length * NetUtils.NumBitsInAByte) {
180             try {
181                 throw new BufferException(
182                         "Trying to read more bits than contained in the data buffer");
183             } catch (BufferException e) {
184                 logger.error("", e);
185             }
186         }
187         int startOffset = data.length * NetUtils.NumBitsInAByte - numBits;
188         byte[] bits = null;
189         try {
190             bits = BitBufferHelper.getBits(data, startOffset, numBits);
191         } catch (BufferException e) {
192             logger.error("", e);
193         }
194         return (long) toNumber(bits, numBits);
195     }
196
197     /**
198      * Reads the specified number of bits from the passed byte array
199      * starting to read from the specified offset
200      * The bits read are stored in a byte array which size is dictated
201      * by the number of bits to be stored.
202      * The bits are stored in the byte array LSB aligned.
203      *
204      * Ex.
205      * Read 7 bits at offset 10
206      * 0         9 10     16 17
207      * 0101000010 | 0000101 | 1111001010010101011
208      * will be returned as {0,0,0,0,0,1,0,1}
209      *
210      * @param byte[] data
211      * @param int startOffset - offset to start fetching bits from data from
212      * @param int numBits - number of bits to be fetched from data
213      * @return byte [] - LSB aligned bits
214      *
215      * @throws BufferException
216      *             when the startOffset and numBits parameters are not congruent
217      *             with the data buffer size
218      */
219     public static byte[] getBits(byte[] data, int startOffset, int numBits)
220             throws BufferException {
221
222         int startByteOffset = 0;
223         int valfromcurr, valfromnext;
224         int extranumBits = numBits % NetUtils.NumBitsInAByte;
225         int extraOffsetBits = startOffset % NetUtils.NumBitsInAByte;
226         int numBytes = (numBits % NetUtils.NumBitsInAByte != 0) ? 1 + numBits
227                 / NetUtils.NumBitsInAByte : numBits / NetUtils.NumBitsInAByte;
228         byte[] shiftedBytes = new byte[numBytes];
229         startByteOffset = startOffset / NetUtils.NumBitsInAByte;
230         byte[] bytes = new byte[numBytes];
231         if (numBits == 0) {
232             return bytes;
233         }
234
235         checkExceptions(data, startOffset, numBits);
236
237         if (extraOffsetBits == 0) {
238             if (extranumBits == 0) {
239                 System.arraycopy(data, startByteOffset, bytes, 0, numBytes);
240                 return bytes;
241             } else {
242                 System.arraycopy(data, startByteOffset, bytes, 0, numBytes - 1);
243                 bytes[numBytes - 1] = (byte) ((int) data[startByteOffset
244                         + numBytes - 1] & getMSBMask(extranumBits));
245             }
246         } else {
247             int i;
248             for (i = 0; i < numBits / NetUtils.NumBitsInAByte; i++) {
249                 // Reading numBytes starting from offset
250                 valfromcurr = (data[startByteOffset + i])
251                         & getLSBMask(NetUtils.NumBitsInAByte - extraOffsetBits);
252                 valfromnext = (data[startByteOffset + i + 1])
253                         & getMSBMask(extraOffsetBits);
254                 bytes[i] = (byte) (valfromcurr << (extraOffsetBits) | (valfromnext >> (NetUtils.NumBitsInAByte - extraOffsetBits)));
255             }
256             // Now adding the rest of the bits if any
257             if (extranumBits != 0) {
258                 if (extranumBits < (NetUtils.NumBitsInAByte - extraOffsetBits)) {
259                     valfromnext = (byte) (data[startByteOffset + i] & ((getMSBMask(extranumBits)) >> extraOffsetBits));
260                     bytes[i] = (byte) (valfromnext << extraOffsetBits);
261                 } else if (extranumBits == (NetUtils.NumBitsInAByte - extraOffsetBits)) {
262                     valfromcurr = (data[startByteOffset + i])
263                             & getLSBMask(NetUtils.NumBitsInAByte
264                                     - extraOffsetBits);
265                     bytes[i] = (byte) (valfromcurr << extraOffsetBits);
266                 } else {
267                     valfromcurr = (data[startByteOffset + i])
268                             & getLSBMask(NetUtils.NumBitsInAByte
269                                     - extraOffsetBits);
270                     valfromnext = (data[startByteOffset + i + 1])
271                             & (getMSBMask(extranumBits
272                                     - (NetUtils.NumBitsInAByte - extraOffsetBits)));
273                     bytes[i] = (byte) (valfromcurr << (extraOffsetBits) | (valfromnext >> (NetUtils.NumBitsInAByte - extraOffsetBits)));
274                 }
275
276             }
277         }
278         // Aligns the bits to LSB
279         shiftedBytes = shiftBitsToLSB(bytes, numBits);
280         return shiftedBytes;
281     }
282
283     // Setters
284     // data: array where data will be stored
285     // input: the data that need to be stored in the data array
286     // startOffset: bit from where to start writing
287     // numBits: number of bits to read
288
289     /**
290      * Bits are expected to be stored in the input byte array from LSB
291      * @param byte[] - data to set the input byte
292      * @param byte - input byte to be inserted
293      * @param startOffset - offset of data[] to start inserting byte from
294      * @param numBits - number of bits of input to be inserted into data[]
295      *
296      * @throws BufferException
297      *             when the input, startOffset and numBits are not congruent
298      *             with the data buffer size
299      */
300     public static void setByte(byte[] data, byte input, int startOffset,
301             int numBits) throws BufferException {
302         byte[] inputByteArray = new byte[1];
303         Arrays.fill(inputByteArray, 0, 1, input);
304         setBytes(data, inputByteArray, startOffset, numBits);
305     }
306
307     /**
308      * Bits are expected to be stored in the input byte array from LSB
309      * @param byte[] - data to set the input byte
310      * @param byte[] - input bytes to be inserted
311      * @param startOffset - offset of data[] to start inserting byte from
312      * @param numBits - number of bits of input to be inserted into data[]
313      * @return void
314      * @throws BufferException
315      *             when the startOffset and numBits parameters are not congruent
316      *             with data and input buffers' size
317      */
318     public static void setBytes(byte[] data, byte[] input, int startOffset,
319             int numBits) throws BufferException {
320         checkExceptions(data, startOffset, numBits);
321         insertBits(data, input, startOffset, numBits);
322     }
323
324     /**
325      * Returns numBits 1's in the MSB position
326      *
327      * @param numBits
328      * @return
329      */
330     public static int getMSBMask(int numBits) {
331         int mask = 0;
332         for (int i = 0; i < numBits; i++) {
333             mask = mask | (1 << (7 - i));
334         }
335         return mask;
336     }
337
338     /**
339      * Returns numBits 1's in the LSB position
340      *
341      * @param numBits
342      * @return
343      */
344     public static int getLSBMask(int numBits) {
345         int mask = 0;
346         for (int i = 0; i < numBits; i++) {
347             mask = mask | (1 << i);
348         }
349         return mask;
350     }
351
352     /**
353      * Returns the numerical value of the byte array passed
354      *
355      * @param byte[] - array
356      * @return long - numerical value of byte array passed
357      */
358     static public long toNumber(byte[] array) {
359         long ret = 0;
360         long length = array.length;
361         int value = 0;
362         for (int i = 0; i < length; i++) {
363             value = array[i];
364             if (value < 0)
365                 value += 256;
366             ret = ret
367                     | (long) ((long) value << ((length - i - 1) * NetUtils.NumBitsInAByte));
368         }
369         return ret;
370     }
371
372     /**
373      * Returns the numerical value of the last numBits (LSB bits) of the byte
374      * array passed
375      *
376      * @param byte[] - array
377      * @param int - numBits
378      * @return long - numerical value of byte array passed
379      */
380     static public long toNumber(byte[] array, int numBits) {
381         int length = numBits / NetUtils.NumBitsInAByte;
382         int bitsRest = numBits % NetUtils.NumBitsInAByte;
383         int startOffset = array.length - length;
384         long ret = 0;
385         int value = 0;
386
387         value = array[startOffset - 1] & getLSBMask(bitsRest);
388         value = (array[startOffset - 1] < 0) ? (array[startOffset - 1] + 256)
389                 : array[startOffset - 1];
390         ret = ret
391                 | (value << ((array.length - startOffset) * NetUtils.NumBitsInAByte));
392
393         for (int i = startOffset; i < array.length; i++) {
394             value = array[i];
395             if (value < 0)
396                 value += 256;
397             ret = ret
398                     | (long) ((long) value << ((array.length - i - 1) * NetUtils.NumBitsInAByte));
399         }
400
401         return ret;
402     }
403
404     /**
405      * Accepts a number as input and returns its value in byte form in LSB
406      * aligned form example: input = 5000 [1001110001000] bytes = 19, -120
407      * [00010011] [10001000]
408      *
409      * @param Number
410      * @return byte[]
411      *
412      */
413
414     public static byte[] toByteArray(Number input) {
415         Class<? extends Number> dataType = input.getClass();
416         short size = 0;
417         long longValue = input.longValue();
418
419         if (dataType == Byte.class || dataType == byte.class) {
420             size = Byte.SIZE;
421         } else if (dataType == Short.class || dataType == short.class) {
422             size = Short.SIZE;
423         } else if (dataType == Integer.class || dataType == int.class) {
424             size = Integer.SIZE;
425         } else if (dataType == Long.class || dataType == long.class) {
426             size = Long.SIZE;
427         } else {
428             throw new IllegalArgumentException(
429                     "Parameter must one of the following: Short/Int/Long\n");
430         }
431
432         int length = size / NetUtils.NumBitsInAByte;
433         byte bytes[] = new byte[length];
434
435         // Getting the bytes from input value
436         for (int i = 0; i < length; i++) {
437             bytes[i] = (byte) ((longValue >> (NetUtils.NumBitsInAByte * (length
438                     - i - 1))) & ByteMask);
439         }
440         return bytes;
441     }
442
443     /**
444      * Accepts a number as input and returns its value in byte form in MSB
445      * aligned form example: input = 5000 [1001110001000] bytes = -114, 64
446      * [10011100] [01000000]
447      *
448      * @param Number
449      *            input
450      * @param int numBits - the number of bits to be returned
451      * @return byte[]
452      *
453      */
454     public static byte[] toByteArray(Number input, int numBits) {
455         Class<? extends Number> dataType = input.getClass();
456         short size = 0;
457         long longValue = input.longValue();
458
459         if (dataType == Short.class) {
460             size = Short.SIZE;
461         } else if (dataType == Integer.class) {
462             size = Integer.SIZE;
463         } else if (dataType == Long.class) {
464             size = Long.SIZE;
465         } else {
466             throw new IllegalArgumentException(
467                     "Parameter must one of the following: Short/Int/Long\n");
468         }
469
470         int length = size / NetUtils.NumBitsInAByte;
471         byte bytes[] = new byte[length];
472         byte[] inputbytes = new byte[length];
473         byte shiftedBytes[];
474
475         // Getting the bytes from input value
476         for (int i = 0; i < length; i++) {
477             bytes[i] = (byte) ((longValue >> (NetUtils.NumBitsInAByte * (length
478                     - i - 1))) & ByteMask);
479         }
480
481         if ((bytes[0] == 0 && dataType == Long.class)
482                 || (bytes[0] == 0 && dataType == Integer.class)) {
483             int index = 0;
484             for (index = 0; index < length; ++index) {
485                 if (bytes[index] != 0) {
486                     bytes[0] = bytes[index];
487                     break;
488                 }
489             }
490             System.arraycopy(bytes, index, inputbytes, 0, length - index);
491             Arrays.fill(bytes, length - index + 1, length - 1, (byte) 0);
492         } else {
493             System.arraycopy(bytes, 0, inputbytes, 0, length);
494         }
495
496         shiftedBytes = shiftBitsToMSB(inputbytes, numBits);
497
498         return shiftedBytes;
499     }
500
501     /**
502      * Takes an LSB aligned byte array and returned the LSB numBits in a MSB
503      * aligned byte array
504      *
505      * @param inputbytes
506      * @param numBits
507      * @return
508      */
509     /**
510      * It aligns the last numBits bits to the head of the byte array following
511      * them with numBits % 8 zero bits.
512      *
513      * Example: For inputbytes = [00000111][01110001] and numBits = 12 it
514      * returns: shiftedBytes = [01110111][00010000]
515      *
516      * @param byte[] inputBytes
517      * @param int numBits - number of bits to be left aligned
518      * @return byte[]
519      */
520     public static byte[] shiftBitsToMSB(byte[] inputBytes, int numBits) {
521         int numBitstoShiftBy = 0, leadZeroesMSB = 8, numEndRestBits = 0;
522         int size = inputBytes.length;
523         byte[] shiftedBytes = new byte[size];
524         int i;
525
526         for (i = 0; i < Byte.SIZE; i++) {
527             if (((byte) (inputBytes[0] & getMSBMask(i + 1))) != 0) {
528                 leadZeroesMSB = i;
529                 break;
530             }
531         }
532
533         if (numBits % NetUtils.NumBitsInAByte == 0) {
534             numBitstoShiftBy = 0;
535         } else {
536             numBitstoShiftBy = ((NetUtils.NumBitsInAByte - (numBits % NetUtils.NumBitsInAByte)) < leadZeroesMSB) ? (NetUtils.NumBitsInAByte - (numBits % NetUtils.NumBitsInAByte))
537                     : leadZeroesMSB;
538         }
539         if (numBitstoShiftBy == 0) {
540             return inputBytes;
541         }
542
543         if (numBits < NetUtils.NumBitsInAByte) {
544             // inputbytes.length = 1 OR read less than a byte
545             shiftedBytes[0] = (byte) ((inputBytes[0] & getLSBMask(numBits)) << numBitstoShiftBy);
546         } else {
547             // # of bits to read from last byte
548             numEndRestBits = NetUtils.NumBitsInAByte
549                     - (inputBytes.length * NetUtils.NumBitsInAByte - numBits - numBitstoShiftBy);
550
551             for (i = 0; i < (size - 1); i++) {
552                 if ((i + 1) == (size - 1)) {
553                     if (numEndRestBits > numBitstoShiftBy) {
554                         shiftedBytes[i] = (byte) ((inputBytes[i] << numBitstoShiftBy) | ((inputBytes[i + 1] & getMSBMask(numBitstoShiftBy)) >> (numEndRestBits - numBitstoShiftBy)));
555                         shiftedBytes[i + 1] = (byte) ((inputBytes[i + 1] & getLSBMask(numEndRestBits
556                                 - numBitstoShiftBy)) << numBitstoShiftBy);
557                     } else
558                         shiftedBytes[i] = (byte) ((inputBytes[i] << numBitstoShiftBy) | ((inputBytes[i + 1] & getMSBMask(numEndRestBits)) >> (NetUtils.NumBitsInAByte - numEndRestBits)));
559                 }
560                 shiftedBytes[i] = (byte) ((inputBytes[i] << numBitstoShiftBy) | (inputBytes[i + 1] & getMSBMask(numBitstoShiftBy)) >> (NetUtils.NumBitsInAByte - numBitstoShiftBy));
561             }
562
563         }
564         return shiftedBytes;
565     }
566
567     /**
568      * It aligns the first numBits bits to the right end of the byte array
569      * preceding them with numBits % 8 zero bits.
570      *
571      * Example: For inputbytes = [01110111][00010000] and numBits = 12 it
572      * returns: shiftedBytes = [00000111][01110001]
573      *
574      * @param byte[] inputBytes
575      * @param int numBits - number of bits to be right aligned
576      * @return byte[]
577      */
578     public static byte[] shiftBitsToLSB(byte[] inputBytes, int numBits) {
579         int numBytes = inputBytes.length;
580         int numBitstoShift = numBits % NetUtils.NumBitsInAByte;
581         byte[] shiftedBytes = new byte[numBytes];
582         int inputLsb = 0, inputMsb = 0;
583
584         if (numBitstoShift == 0) {
585             return inputBytes;
586         }
587
588         for (int i = 1; i < numBytes; i++) {
589             inputLsb = inputBytes[i - 1]
590                     & getLSBMask(NetUtils.NumBitsInAByte - numBitstoShift);
591             inputLsb = (inputLsb < 0) ? (inputLsb + 256) : inputLsb;
592             inputMsb = inputBytes[i] & getMSBMask(numBitstoShift);
593             inputMsb = (inputBytes[i] < 0) ? (inputBytes[i] + 256)
594                     : inputBytes[i];
595             shiftedBytes[i] = (byte) ((inputLsb << numBitstoShift) | (inputMsb >> (NetUtils.NumBitsInAByte - numBitstoShift)));
596         }
597         inputMsb = inputBytes[0] & (getMSBMask(numBitstoShift));
598         inputMsb = (inputMsb < 0) ? (inputMsb + 256) : inputMsb;
599         shiftedBytes[0] = (byte) (inputMsb >> (NetUtils.NumBitsInAByte - numBitstoShift));
600         return shiftedBytes;
601     }
602
603     /**
604      * Insert in the data buffer at position dictated by the offset the number
605      * of bits specified from the input data byte array. The input byte array
606      * has the bits stored starting from the LSB
607      *
608      * @param byte[] data
609      * @param byte[] inputdata
610      * @param int startOffset
611      * @param int numBits
612      */
613     public static void insertBits(byte[] data, byte[] inputdataLSB,
614             int startOffset, int numBits) {
615         byte[] inputdata = shiftBitsToMSB(inputdataLSB, numBits); // Align to
616                                                                   // MSB the
617                                                                   // passed byte
618                                                                   // array
619         int numBytes = numBits / NetUtils.NumBitsInAByte;
620         int startByteOffset = startOffset / NetUtils.NumBitsInAByte;
621         int extraOffsetBits = startOffset % NetUtils.NumBitsInAByte;
622         int extranumBits = numBits % NetUtils.NumBitsInAByte;
623         int RestBits = numBits % NetUtils.NumBitsInAByte;
624         int InputMSBbits = 0, InputLSBbits = 0;
625         int i;
626
627         if (numBits == 0) {
628             return;
629         }
630
631         if (extraOffsetBits == 0) {
632             if (extranumBits == 0) {
633                 numBytes = numBits / NetUtils.NumBitsInAByte;
634                 System.arraycopy(inputdata, 0, data, startByteOffset, numBytes);
635             } else {
636                 System.arraycopy(inputdata, 0, data, startByteOffset, numBytes);
637                 data[startByteOffset + numBytes] = (byte) (data[startByteOffset
638                         + numBytes] | (inputdata[numBytes] & getMSBMask(extranumBits)));
639             }
640         } else {
641             for (i = 0; i < numBytes; i++) {
642                 if (i != 0)
643                     InputLSBbits = (inputdata[i - 1] & getLSBMask(extraOffsetBits));
644                 InputMSBbits = (byte) (inputdata[i] & (getMSBMask(NetUtils.NumBitsInAByte
645                         - extraOffsetBits)));
646                 InputMSBbits = (InputMSBbits >= 0) ? InputMSBbits
647                         : InputMSBbits + 256;
648                 data[startByteOffset + i] = (byte) (data[startByteOffset + i]
649                         | (InputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits)) | (InputMSBbits >> extraOffsetBits));
650                 InputMSBbits = InputLSBbits = 0;
651             }
652             if (RestBits < (NetUtils.NumBitsInAByte - extraOffsetBits)) {
653                 if (numBytes != 0)
654                     InputLSBbits = (inputdata[i - 1] & getLSBMask(extraOffsetBits));
655                 InputMSBbits = (byte) (inputdata[i] & (getMSBMask(RestBits)));
656                 InputMSBbits = (InputMSBbits >= 0) ? InputMSBbits
657                         : InputMSBbits + 256;
658                 data[startByteOffset + i] = (byte) ((data[startByteOffset + i])
659                         | (InputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits)) | (InputMSBbits >> extraOffsetBits));
660             } else if (RestBits == (NetUtils.NumBitsInAByte - extraOffsetBits)) {
661                 if (numBytes != 0)
662                     InputLSBbits = (inputdata[i - 1] & getLSBMask(extraOffsetBits));
663                 InputMSBbits = (byte) (inputdata[i] & (getMSBMask(NetUtils.NumBitsInAByte
664                         - extraOffsetBits)));
665                 InputMSBbits = (InputMSBbits >= 0) ? InputMSBbits
666                         : InputMSBbits + 256;
667                 data[startByteOffset + i] = (byte) (data[startByteOffset + i]
668                         | (InputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits)) | (InputMSBbits >> extraOffsetBits));
669             } else {
670                 if (numBytes != 0)
671                     InputLSBbits = (inputdata[i - 1] & getLSBMask(extraOffsetBits));
672                 InputMSBbits = (byte) (inputdata[i] & (getMSBMask(NetUtils.NumBitsInAByte
673                         - extraOffsetBits)));
674                 InputMSBbits = (InputMSBbits >= 0) ? InputMSBbits
675                         : InputMSBbits + 256;
676                 data[startByteOffset + i] = (byte) (data[startByteOffset + i]
677                         | (InputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits)) | (InputMSBbits >> extraOffsetBits));
678
679                 InputLSBbits = (inputdata[i] & (getLSBMask(RestBits
680                         - (NetUtils.NumBitsInAByte - extraOffsetBits)) << (NetUtils.NumBitsInAByte - RestBits)));
681                 data[startByteOffset + i + 1] = (byte) (data[startByteOffset
682                         + i + 1] | (InputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits)));
683             }
684         }
685     }
686
687     /**
688      * Checks for overflow and underflow exceptions
689      * @param data
690      * @param startOffset
691      * @param numBits
692      * @throws PacketException when the startOffset and numBits parameters
693      *                    are not congruent with the data buffer's size
694      */
695     public static void checkExceptions(byte[] data, int startOffset, int numBits)
696             throws BufferException {
697         int endOffsetByte;
698         int startByteOffset;
699         endOffsetByte = startOffset
700                 / NetUtils.NumBitsInAByte
701                 + numBits
702                 / NetUtils.NumBitsInAByte
703                 + ((numBits % NetUtils.NumBitsInAByte != 0) ? 1 : ((startOffset
704                         % NetUtils.NumBitsInAByte != 0) ? 1 : 0));
705         startByteOffset = startOffset / NetUtils.NumBitsInAByte;
706
707         if (data == null) {
708             throw new BufferException("data[] is null\n");
709         }
710
711         if ((startOffset < 0) || (startByteOffset >= data.length)
712                 || (endOffsetByte > data.length) || (numBits < 0)
713                 || (numBits > NetUtils.NumBitsInAByte * data.length)) {
714             throw new BufferException(
715                     "Illegal arguement/out of bound exception - data.length = "
716                             + data.length + " startOffset = " + startOffset
717                             + " numBits " + numBits);
718         }
719     }
720 }