1 /*
2  * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 package nsk.share.jdwp;
25 
26 import java.io.*;
27 import nsk.share.*;
28 
29 /**
30  * This class represents a byte buffer of variable size.
31  */
32 public class ByteBuffer {
33 
34     /**
35      * Empty byte value (zero).
36      */
37     private static final byte EMPTY_BYTE = (byte)0;
38 
39     /**
40      * Current number of bytes in the buffer.
41      */
42     private int CurrentSize;
43 
44     /**
45      * Delta to increase buffer size.
46      */
47     private int Delta;
48 
49     /**
50      * Current offset from the buffer begin during parsing packet.
51      */
52     int parseOffset;
53 
54     /**
55      * Array of bytes in the buffer.
56      */
57     protected byte[] bytes;
58 
59     /**
60      * Make an empty <code>ByteBuffer</code> object.
61      */
ByteBuffer()62     public ByteBuffer() {
63         this(128, 128);
64     }
65 
66     /**
67      * Make an empty <code>ByteBuffer</code> object with given initial capacity.
68      * When there is no space for a new byte in a buffer it's capacity
69      * grows by Delta.
70      */
ByteBuffer(int InitialSize, int Delta)71     public ByteBuffer(int InitialSize, int Delta) {
72         if (Delta <= 0)
73             Delta = 16;
74         this.Delta = Delta;
75         CurrentSize = 0;
76         bytes = new byte[InitialSize];
77         parseOffset = 0;
78     }
79 
80     /**
81      * Make a copy of specified byte buffer.
82      */
ByteBuffer(ByteBuffer buffer)83     public ByteBuffer(ByteBuffer buffer) {
84         int InitialSize = buffer.bytes.length;
85         Delta = buffer.Delta;
86         CurrentSize = buffer.CurrentSize;
87         bytes = new byte[InitialSize];
88         for (int i = 0; i < CurrentSize; i++ ) {
89             bytes[i] = buffer.bytes[i];
90         }
91         parseOffset = 0;
92     }
93 
94     /**
95      * Return number of bytes in this buffer.
96      */
length()97     public int length() {
98         return CurrentSize;
99     }
100 
101     /**
102      * Return array of bytes in this buffer.
103      */
getBytes()104     public byte[] getBytes() {
105         return bytes;
106     }
107 
108     //////////////////////////////////////////////////////////////////////////
109 
110     /**
111      * Replace the byte at the specified offset in this buffer with the
112      * less significant byte from the int value.
113      *
114      * @throws BoundException if specified offset is out of buffer bounds
115      */
putByte(int off, byte value)116     public void putByte(int off, byte value) throws BoundException {
117 
118         if ((off < 0) || (off >= CurrentSize))
119             throw new BoundException("Unable to put one byte at " + offsetString(off));
120 
121         bytes[off] = value;
122     }
123 
124     /**
125      * Replace len bytes starting at offset off with the bytes from the
126      * given byte array.
127      *
128      * @throws BoundException if offset and length are out of buffer bounds
129      */
putBytes(int off, byte[] value, int start, int len)130     public void putBytes(int off, byte[] value, int start, int len) throws BoundException {
131         if (len > (CurrentSize - off)) {
132             throw new BoundException("Unable to put " + len + " bytes at " + offsetString(off) +
133                                      " (available bytes: " + (CurrentSize - off) + ")" );
134         }
135         try {
136             for (int i = 0; i < len; i++)
137                 putByte(off++, value[start++]);
138         } catch (BoundException e) {
139             throw new Failure("Caught unexpected bound exception while putting " + len +
140                               "bytes at " + offsetString(off) + ":\n\t" + e);
141         }
142     }
143 
144     /**
145      * Replace count (1 - 8) bytes starting at offset off with the less
146      * significant bytes from the specified ID value.
147      *
148      * @throws BoundException if offset and count are out of buffer bounds
149      */
putID(int off, long value, int count)150     public void putID(int off, long value, int count) throws BoundException {
151 
152         if ((count <= 0) || (count > 8))
153             throw new TestBug("Illegal number of bytes of ID value to put: " + count);
154 
155         if (count > CurrentSize - off) {
156             throw new BoundException("Unable to put " + count + " bytes of ID value at " +
157                                      offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
158         }
159 
160         try {
161             putValueBytes(off, value, count);
162         } catch (BoundException e) {
163             throw new Failure("Caught unexpected bound exception while putting " + count +
164                               "bytes of ID value at " + offsetString(off) + ":\n\t" + e);
165         }
166     }
167 
168     /**
169      * Replace four bytes starting at offset off with the bytes from the
170      * specified int value.
171      *
172      * @throws BoundException if offset is out of buffer bounds
173      */
putInt(int off, int value)174     public void putInt(int off, int value) throws BoundException {
175         final int count = JDWP.TypeSize.INT;
176 
177         if (count > CurrentSize - off) {
178             throw new BoundException("Unable to put " + count + " bytes of int value at " +
179                                      offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
180         }
181 
182         try {
183             putValueBytes(off, value, count);
184         } catch (BoundException e) {
185             throw new Failure("Caught unexpected bound exception while putting " + count +
186                               "bytes of int value at " + offsetString(off) + ":\n\t" + e);
187         }
188     }
189 
190     /**
191      * Replace two bytes starting at offset off with the bytes
192      * from the specified short value.
193      *
194      * @throws BoundException if offset is out of buffer bounds
195      */
putShort(int off, short value)196     public void putShort(int off, short value) throws BoundException {
197         final int count = JDWP.TypeSize.SHORT;
198 
199         if (count > CurrentSize - off) {
200             throw new BoundException("Unable to put " + count + " bytes of short value at " +
201                                      offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
202         }
203 
204         try {
205             putValueBytes(off, value, count);
206         } catch (BoundException e) {
207             throw new Failure("Caught unexpected bound exception while putting " + count +
208                               "bytes of short value at " + offsetString(off) + ":\n\t" + e);
209         }
210     }
211 
212     /**
213      * Replace eight bytes starting at offset off with the bytes
214      * from the specified long value.
215      *
216      * @throws BoundException if offset is out of buffer bounds
217      */
putLong(int off, long value)218     public void putLong(int off, long value) throws BoundException {
219         final int count = JDWP.TypeSize.LONG;
220 
221         if (count > CurrentSize - off) {
222             throw new BoundException("Unable to put " + count + " bytes of long value at " +
223                                      offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
224         }
225 
226         try {
227             putValueBytes(off, value, count);
228         } catch (BoundException e) {
229             throw new Failure("Caught unexpected bound exception while putting " + count +
230                               "bytes of long value at " + offsetString(off) + ":\n\t" + e);
231         }
232     }
233 
234     /**
235      * Replace four bytes starting at offset off with the bytes
236      * from the specified float value.
237      *
238      * @throws BoundException if offset is out of buffer bounds
239      */
putFloat(int off, float value)240     public void putFloat(int off, float value) throws BoundException {
241         final int count = JDWP.TypeSize.FLOAT;
242 
243         if (count > CurrentSize - off) {
244             throw new BoundException("Unable to put " + count + " bytes of float value at " +
245                                      offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
246         }
247 
248         try {
249             long l = Float.floatToIntBits(value);
250             putValueBytes(off, l, count);
251         } catch (BoundException e) {
252             throw new Failure("Caught unexpected bound exception while putting " + count +
253                               "bytes of float value at " + offsetString(off) + ":\n\t" + e);
254         }
255     }
256 
257     /**
258      * Replace eight bytes starting at offset off with the bytes
259      * from the specified double value.
260      *
261      * @throws BoundException if offset is out of buffer bounds
262      */
putDouble(int off, double value)263     public void putDouble(int off, double value) throws BoundException {
264         final int count = JDWP.TypeSize.DOUBLE;
265 
266         if (count > CurrentSize - off) {
267             throw new BoundException("Unable to put " + count + " bytes of double value at " +
268                                      offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
269         }
270 
271         try {
272             long l = Double.doubleToLongBits(value);
273             putValueBytes(off, l, count);
274         } catch (BoundException e) {
275             throw new Failure("Caught unexpected bound exception while putting " + count +
276                               "bytes of double value at " + offsetString(off) + ": \n\t" + e);
277         }
278     }
279 
280     /**
281      * Replace two bytes starting at offset off with the bytes
282      * from the specified char value.
283      *
284      * @throws BoundException if offset is out of buffer bounds
285      */
putChar(int off, char value)286     public void putChar(int off, char value) throws BoundException {
287         final int count = JDWP.TypeSize.CHAR;
288 
289         if (count > CurrentSize - off) {
290             throw new BoundException("Unable to put " + count + " bytes of char value at " +
291                                      offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
292         }
293 
294         try {
295             long l = (long)value;
296             putValueBytes(off, l, count);
297         } catch (BoundException e) {
298             throw new Failure("Caught unexpected bound exception while putting " + count +
299                               "bytes of char value at " + offsetString(off) + ":\n\t" + e);
300         }
301     }
302 
303     //////////////////////////////////////////////////////////////////////////
304 
305     /**
306      * Append the specified byte to the end of this buffer.
307      */
addByte(byte value)308     public void addByte(byte value) {
309         checkSpace(1);
310 
311         int where = CurrentSize;
312         CurrentSize++;
313 
314         try {
315             putByte(where, value);
316         }
317         catch (BoundException e) {
318             throw new TestBug("Caught unexpected bound exception while adding one byte:\n\t"
319                             + e);
320         };
321     }
322 
323     /**
324      * Append specified byte value repeated count to the end of this buffer.
325      */
addBytes(byte value, int count)326     public void addBytes(byte value, int count) {
327         checkSpace(count);
328         for (int i = 0; i < count; i++) {
329             addByte(value);
330         }
331     }
332 
333     /**
334      * Append the bytes from the specified byte array to the end of this buffer.
335      */
addBytes(byte[] value, int start, int len)336     public void addBytes(byte[] value, int start, int len) {
337         checkSpace(len);
338 
339         int where = CurrentSize;
340         CurrentSize = CurrentSize + len;
341 
342         try {
343             putBytes(where, value, start, len);
344         }
345         catch (BoundException e) {
346             throw new TestBug("Caught unexpected bound exception while adding " +
347                                len + " bytes:\n\t" + e);
348         };
349     }
350 
351     /**
352      * Appends the count (1 - 8) less significant bytes from the
353      * specified ID value to the end of this buffer.
354      */
addID(long value, int count)355     public void addID(long value, int count) {
356         if ((count <= 0) || (count > 8))
357             throw new TestBug("Illegal number bytes of ID value to add: " + count);
358 
359         final int where = CurrentSize;
360         addBytes(EMPTY_BYTE, count);
361 
362         try {
363             putID(where, value, count);
364         }
365         catch (BoundException e) {
366             throw new TestBug("Caught unexpected bound exception while adding " +
367                                count + " bytes of ID value:\n\t" + e);
368         };
369     }
370 
371     /**
372      * Append four bytes from the specified int value to the
373      * end of this buffer.
374      */
addInt(int value)375     public void addInt(int value) {
376         final int count = JDWP.TypeSize.INT;
377         final int where = CurrentSize;
378         addBytes(EMPTY_BYTE, count);
379 
380         try {
381             putInt(where, value);
382         }
383         catch (BoundException e) {
384             throw new TestBug("Caught unexpected bound exception while adding " +
385                                count + " bytes of int value:\n\t" + e);
386         };
387     }
388 
389     /**
390      * Append two bytes from the specified int value to the
391      * end of this buffer.
392      */
addShort(short value)393     public void addShort(short value) {
394         final int count = JDWP.TypeSize.SHORT;
395         final int where = CurrentSize;
396         addBytes(EMPTY_BYTE, count);
397         try {
398             putShort(where, value);
399         }
400         catch (BoundException e) {
401             throw new TestBug("Caught unexpected bound exception while adding " +
402                                count + " bytes of short value:\n\t" + e);
403         };
404     }
405 
406     /**
407      * Appends eight bytes from the specified long
408      * value to the end of this buffer.
409      */
addLong(long value)410     public void addLong(long value) {
411         final int count = JDWP.TypeSize.LONG;
412         final int where = CurrentSize;
413         addBytes(EMPTY_BYTE, count);
414         try {
415             putLong(where, value);
416         }
417         catch (BoundException e) {
418             throw new TestBug("Caught unexpected bound exception while adding " +
419                                count + " bytes of long value:\n\t" + e);
420         };
421     }
422 
423     /**
424      * Appends four bytes from the specified float
425      * value to the end of this buffer.
426      */
addFloat(float value)427     public void addFloat(float value) {
428         final int count = JDWP.TypeSize.FLOAT;
429         final int where = CurrentSize;
430         addBytes(EMPTY_BYTE, count);
431         try {
432             putFloat(where, value);
433         }
434         catch (BoundException e) {
435             throw new TestBug("Caught unexpected bound exception while adding " +
436                                count + " bytes of float value:\n\t" + e);
437         };
438     }
439 
440     /**
441      * Appends eight bytes from the specified double
442      * value to the end of this buffer.
443      */
addDouble(double value)444     public void addDouble(double value) {
445         final int count = JDWP.TypeSize.DOUBLE;
446         final int where = CurrentSize;
447         addBytes(EMPTY_BYTE, count);
448         try {
449             putDouble(where, value);
450         }
451         catch (BoundException e) {
452             throw new TestBug("Caught unexpected bound exception while adding " +
453                                count + " bytes of double value:\n\t" + e);
454         };
455     }
456 
457     /**
458      * Appends four bytes from the specified char
459      * value to the end of this buffer.
460      */
addChar(char value)461     public void addChar(char value) {
462         final int count = JDWP.TypeSize.CHAR;
463         final int where = CurrentSize;
464         addBytes(EMPTY_BYTE, count);
465         try {
466             putChar(where, value);
467         }
468         catch (BoundException e) {
469             throw new TestBug("Caught unexpected bound exception while adding " +
470                                count + " bytes of float value:\n\t" + e);
471         };
472     }
473 
474     //////////////////////////////////////////////////////////////////////////
475 
476     /**
477      * Read a byte value from this buffer at the specified position.
478      *
479      * @throws BoundException if there are no bytes at this position
480      */
getByte(int off)481     public byte getByte(int off) throws BoundException {
482         if (off < 0 || off >= CurrentSize) {
483             throw new BoundException("Unable to get one byte at " + offsetString(off) +
484                                     ": no bytes available");
485         }
486         return bytes[off];
487     }
488 
489     /**
490      * Read count bytes (1-8) from this buffer at the specified
491      * position and returns a long value composed of these bytes.
492      *
493      * @throws BoundException if there are no so many bytes at this position
494      */
getID(int off, int count)495     public long getID(int off, int count) throws BoundException {
496         if ((count <= 0) || (count > 8))
497             throw new TestBug("Illegal number of bytes of ID value to get: " + count);
498 
499         if (count > CurrentSize - off) {
500             throw new BoundException("Unable to get " + count + " bytes of ID value at " +
501                                      offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
502         }
503 
504         try {
505             return getValueBytes(off, count);
506         }
507         catch (BoundException e) {
508             throw new TestBug("Caught unexpected bound exception while getting " +
509                                count + " bytes of ID value at " + offsetString(off) + ":\n\t" + e);
510         }
511     }
512 
513     /**
514      * Read four bytes from this buffer at the specified
515      * position and returns an integer value composed of these bytes.
516      *
517      * @throws BoundException if there are no so many bytes at this position
518      */
getInt(int off)519     public int getInt(int off) throws BoundException {
520         final int count = JDWP.TypeSize.INT;
521         if (count > CurrentSize - off) {
522             throw new BoundException("Unable to get " + count + " bytes of int value at " +
523                                      offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
524         }
525 
526         try {
527             return (int)getValueBytes(off, count);
528         }
529         catch (BoundException e) {
530             throw new TestBug("Caught unexpected bound exception while getting " +
531                                count + " bytes of int value at " + offsetString(off) + ":\n\t" + e);
532         }
533     }
534 
535     /**
536      * Read two bytes from this buffer at the specified
537      * position and returns a short value composed of these bytes.
538      *
539      * @throws BoundException if there are no so many bytes at this position
540      */
getShort(int off)541     public short getShort(int off) throws BoundException {
542         final int count = JDWP.TypeSize.SHORT;
543         if (count > CurrentSize - off) {
544             throw new BoundException("Unable to get " + count + " bytes of short value at " +
545                                      offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
546         }
547 
548         try {
549             return (short)getValueBytes(off, count);
550         }
551         catch (BoundException e) {
552             throw new TestBug("Caught unexpected bound exception while getting " +
553                                count + " bytes of short value at " + offsetString(off) + ":\n\t" + e);
554         }
555     }
556 
557     /**
558      * Read eight bytes from this buffer at the specified
559      * position and returns a long value composed of these bytes.
560      *
561      * @throws BoundException if there are no so many bytes at this position
562      */
getLong(int off)563     public long getLong(int off) throws BoundException {
564         final int count = JDWP.TypeSize.LONG;
565         if (count > CurrentSize - off) {
566             throw new BoundException("Unable to get " + count + " bytes of long value at " +
567                                      offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
568         }
569 
570         try {
571             return getValueBytes(off, count);
572         }
573         catch (BoundException e) {
574             throw new TestBug("Caught unexpected bound exception while getting " +
575                                count + " bytes of long value at " + offsetString(off) + ":\n\t" + e);
576         }
577     }
578 
579     /**
580      * Read eight bytes from this buffer at the specified
581      * position and returns a double value composed of these bytes.
582      *
583      * @throws BoundException if there are no so many bytes at this position
584      */
getDouble(int off)585     public double getDouble(int off) throws BoundException {
586         final int count = JDWP.TypeSize.DOUBLE;
587         if (count > CurrentSize - off) {
588             throw new BoundException("Unable to get " + count + " bytes of double value at " +
589                                      offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
590         }
591 
592         try {
593             long value = getValueBytes(off, count);
594             return Double.longBitsToDouble(value);
595         }
596         catch (BoundException e) {
597             throw new TestBug("Caught unexpected bound exception while getting " +
598                                count + " bytes of long value at " + offsetString(off) + ":\n\t" + e);
599         }
600     }
601 
602     /**
603      * Read four bytes from this buffer at the specified
604      * position and returns a float value composed of these bytes.
605      *
606      * @throws BoundException if there are no so many bytes at this position
607      */
getFloat(int off)608     public float getFloat(int off) throws BoundException {
609         final int count = JDWP.TypeSize.FLOAT;
610         if (count > CurrentSize - off) {
611             throw new BoundException("Unable to get " + count + " bytes of float value at " +
612                                      offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
613         }
614 
615         try {
616             int value = (int)getValueBytes(off, count);
617             return Float.intBitsToFloat(value);
618         }
619         catch (BoundException e) {
620             throw new TestBug("Caught unexpected bound exception while getting " +
621                                count + " bytes of float value at " + offsetString(off) + ":\n\t" + e);
622         }
623     }
624 
625     /**
626      * Read two bytes from this buffer at the specified
627      * position and returns a char value composed of these bytes.
628      *
629      * @throws BoundException if there are no so many bytes at this position
630      */
getChar(int off)631     public char getChar(int off) throws BoundException {
632         final int count = JDWP.TypeSize.CHAR;
633         if (count > CurrentSize - off) {
634             throw new BoundException("Unable to get " + count + " bytes of char value at " +
635                                      offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
636         }
637 
638         try {
639             int value = (int)getValueBytes(off, count);
640             return (char)value;
641         }
642         catch (BoundException e) {
643             throw new TestBug("Caught unexpected bound exception while getting " +
644                                count + " bytes of char value at " + offsetString(off) + ":\n\t" + e);
645         }
646     }
647 
648     //////////////////////////////////////////////////////////////////////////
649 
650     /**
651      * Set the current parser position to 0.
652      */
resetPosition()653     public void resetPosition() {
654         resetPosition(0);
655     }
656 
657     /**
658      * Set the current parser position to the specified value.
659      */
resetPosition(int i)660     public void resetPosition(int i) {
661         parseOffset = i;
662     }
663 
664     /**
665      * Return current parser position.
666      */
currentPosition()667     public int currentPosition() {
668         return parseOffset;
669     }
670 
671     /**
672      * Return true if the parser pointer is set to the end of buffer.
673      */
isParsed()674     public boolean isParsed() {
675         return (parseOffset == CurrentSize);
676     }
677 
678     /**
679      * Read a byte value from this buffer at the current parser position.
680      *
681      * @throws BoundException if there are no more bytes in the buffer
682      */
getByte()683     public byte getByte() throws BoundException {
684         return getByte(parseOffset++);
685     }
686 
687     /**
688      * Read count bytes (1-8) from this buffer at the current parser
689      * position and returns a long value composed of these bytes.
690      *
691      * @throws BoundException if there are no so many bytes in the buffer
692      */
getID(int count)693     public long getID(int count) throws BoundException {
694         long value = getID(parseOffset, count);
695         parseOffset += count;
696         return value;
697     }
698 
699     /**
700      * Read four bytes from this buffer at the current parser
701      * position and returns an integer value composed of these bytes.
702      *
703      * @throws BoundException if there are no so many bytes in the buffer
704      */
getInt()705     public int getInt() throws BoundException {
706         final int count = JDWP.TypeSize.INT;
707         int value = getInt(parseOffset);
708         parseOffset += count;
709         return value;
710     }
711 
712     /**
713      * Read two bytes from this buffer at the current parser
714      * position and returns a short value composed of these bytes.
715      *
716      * @throws BoundException if there are no so many bytes in the buffer
717      */
getShort()718     public short getShort() throws BoundException {
719         final int count = JDWP.TypeSize.SHORT;
720         short value = getShort(parseOffset);
721         parseOffset += count;
722         return value;
723     }
724 
725     /**
726      * Read eight bytes from this buffer at the current parser
727      * position and returns a long value composed of these bytes.
728      *
729      * @throws BoundException if there are no so many bytes in the buffer
730      */
getLong()731     public long getLong() throws BoundException {
732         final int count = JDWP.TypeSize.LONG;
733         long value = getLong(parseOffset);
734         parseOffset += count;
735         return value;
736     }
737 
738     /**
739      * Read eight bytes from this buffer at the current parser
740      * position and returns a double value composed of these bytes.
741      *
742      * @throws BoundException if there are no so many bytes in the buffer
743      */
getDouble()744     public double getDouble() throws BoundException {
745         final int count = JDWP.TypeSize.DOUBLE;
746         double value = getDouble(parseOffset);
747         parseOffset += count;
748         return value;
749     }
750 
751     /**
752      * Read four bytes from this buffer at the current parser
753      * position and returns a float value composed of these bytes.
754      *
755      * @throws BoundException if there are no so many bytes in the buffer
756      */
getFloat()757     public float getFloat() throws BoundException {
758         final int count = JDWP.TypeSize.FLOAT;
759         float value = getFloat(parseOffset);
760         parseOffset += count;
761         return value;
762     }
763 
764     /**
765      * Read two bytes from this buffer at the current parser
766      * position and returns a char value composed of these bytes.
767      *
768      * @throws BoundException if there are no so many bytes in the buffer
769      */
getChar()770     public char getChar() throws BoundException {
771         final int count = JDWP.TypeSize.CHAR;
772         char value = getChar(parseOffset);
773         parseOffset += count;
774         return value;
775     }
776 
777     /**
778      * Remove at least first count bytes from the buffer.
779      */
780 
deleteBytes(int count)781     public void deleteBytes(int count) {
782         int j = 0;
783         while (count < CurrentSize)
784             bytes[j++] = bytes[count++];
785 
786         CurrentSize = j;
787     }
788 
789     /**
790      * Clear the buffer.
791      */
resetBuffer()792     public void resetBuffer() {
793         CurrentSize = 0;
794     }
795 
796     /**
797      * Return string representation of the buffer starting at given offset.
798      */
toString(int start)799     public String toString(int start) {
800 
801         String Result = "", HexLine = "", DisplayLine = "";
802 
803         int j = 0;
804 
805         for (int i = start; i < length(); i++) {
806 
807             HexLine = HexLine + toHexString(bytes[i], 2) + " ";
808 
809             String ch = ".";
810             if (bytes[i] >= 0x20 && bytes[i] < 0x80) {
811                 try {
812                     ch = new String(bytes, i, 1, "US-ASCII");
813                 } catch (UnsupportedEncodingException ignore) {
814                 }
815             }
816             DisplayLine = DisplayLine + ch;
817 
818             if ((i == length() - 1) || (((i - start) & 0x0F) == 0x0F)) {
819                 Result = Result +
820                          "    " +
821                          toHexString(j, 4) + ": " +
822                          PadR(HexLine, 48) + "  " +
823                          DisplayLine + "\n";
824                 HexLine = "";
825                 DisplayLine = "";
826                 j = j + 16;
827             }
828         }
829         return Result;
830     }
831 
832     /**
833      * Return string representation of the buffer.
834      */
toString()835     public String toString() {
836         return toString(0);
837     }
838 
839     /**
840      * Return string with hexadecimal representation of bytes.
841      */
toHexString(long b, int length)842     public static String toHexString(long b, int length) {
843         return Right(Long.toHexString(b), length).replace(' ', '0');
844     }
845 
846     /**
847      * Return string with hexadecimal representation of bytes.
848      */
toHexDecString(long b, int length)849     public static String toHexDecString(long b, int length) {
850         return toHexString(b, length) + " (" + b + ")";
851     }
852 
853     // -----
854 
855     /**
856      * Return string with hexadecimal representation of offset.
857      */
offsetString(int off)858     public static String offsetString(int off) {
859         return "0x" + toHexString(off, 4);
860     }
861 
862     /**
863      * Return string with hexadecimal representation of the current offset.
864      */
offsetString()865     public String offsetString() {
866         return offsetString(currentPosition());
867     }
868 
869     // -----
870 
871     /**
872      * Check if there space for new bytes in the buffer.
873      */
checkSpace(int space)874     protected void checkSpace(int space) {
875 
876         int newSize = CurrentSize + space;
877 
878         if (bytes.length >= newSize)
879             return;
880 
881         byte[] newBytes = new byte[newSize];
882 
883         for (int i = 0; i < CurrentSize; i++)
884             newBytes[i] = bytes[i];
885 
886         bytes = newBytes;
887     }
888 
889     /**
890      * Replace count (1 - 8) bytes starting at offset off with the less
891      * significant bytes from the specified long value.
892      *
893      * @throws BoundException if offset and count are out of buffer bounds
894      */
putValueBytes(int off, long value, int count)895     protected void putValueBytes(int off, long value, int count) throws BoundException {
896         if ((count <= 0) || (count > 8))
897             throw new TestBug("Illegal number of bytes of value to put: " + count);
898 
899         if (count > CurrentSize - off) {
900             throw new BoundException("Unable to put " + count + " bytes of value at " +
901                                      off + " (available bytes: " + (CurrentSize - off) + ")" );
902         }
903 
904         int shift = (count - 1) * 8;
905         for (int i = 0; i < count; i++) {
906             putByte(off++, (byte) ((value >>> shift) & 0xFF));
907             shift = shift - 8;
908         }
909     }
910     /**
911      * Appends the count (1 - 8) less significant bytes from the
912      * specified long value to the end of this buffer.
913      */
addValueBytes(long value, int count)914     protected void addValueBytes(long value, int count) throws BoundException {
915         if ((count <= 0) || (count > 8))
916             throw new TestBug("Illegal number of bytes of value to add: " + count);
917 
918         checkSpace(count);
919 
920         int where = CurrentSize;
921         CurrentSize += count;
922 
923         putValueBytes(where, value, count);
924     }
925 
926     /**
927      * Read count bytes (1-8) from this buffer at the specified
928      * position and returns a long value composed of these bytes.
929      *
930      * @throws BoundException if there are no so many bytes in the buffer
931      */
getValueBytes(int off, int count)932     public long getValueBytes(int off, int count) throws BoundException {
933         if ((count <= 0) || (count > 8))
934             throw new TestBug("Illegal number of bytes of value to get: " + count);
935 
936         long l = 0;
937 
938         for (int i = 0; i < count; i++) {
939             l = (l * 0x100) + ((long) getByte(off + i) & 0xFF);
940         }
941 
942         return l;
943     }
944 
945     /**
946      * Read count bytes (1-8) from this buffer at the current parser
947      * position and returns a long value composed of these bytes.
948      *
949      * @throws BoundException if there are no so many bytes in the buffer
950      */
951 /*
952     protected long getValueBytes(int count) throws BoundException {
953         long value = getValueBytes(parseOffset);
954         parseOffset += count;
955         return value;
956     }
957  */
958 
959     // ---
960 
PadL(String source, int length, String what)961     private static String PadL(String source, int length, String what) {
962 
963         if (length <= 0)
964             return "";
965 
966         if (source.length() > length)
967             return PadL("", length, "*");
968 
969         while (source.length() < length)
970             source = what + source;
971 
972         return source;
973     }
974 
975 
PadL(String source, int length)976     private static String PadL(String source, int length) {
977         return PadL(source, length, " ");
978     }
979 
PadR(String source, int length, String what)980     private static String PadR(String source, int length, String what) {
981 
982         if (length <= 0)
983             return "";
984 
985         if (source.length() > length)
986             return PadR("", length, "*");
987 
988         while (source.length() < length)
989             source = source + what;
990 
991         return source;
992     }
993 
PadR(String source, int length)994     private static String PadR(String source, int length) {
995         return PadR(source, length, " ");
996     }
997 
Left(String source, int length)998     private static String Left(String source, int length) {
999 
1000         if (length <= 0)
1001             return "";
1002 
1003         if (length <= source.length())
1004             return source.substring(0, length);
1005         else
1006             return PadR(source, length);
1007     }
1008 
Right(String source, int length)1009     private static String Right(String source, int length) {
1010 
1011         if (length <= 0)
1012             return "";
1013 
1014         if (length <= source.length())
1015             return source.substring(source.length() - length, source.length());
1016         else
1017             return PadL(source, length);
1018     }
1019 
1020 }
1021