1 /*
  2  * Copyright (c) 2016, 2019, 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 
 25 package gc.stress.gcbasher;
 26 
 27 class ByteCursor {
 28     private int offset;
 29     private byte[] data;
 30 
 31     public ByteCursor(byte[] data) {
 32         this.offset = 0;
 33         this.data = data;
 34     }
 35 
 36     public int getOffset() {
 37         return offset;
 38     }
 39 
 40     public void skipBytes(int n) {
 41         offset += n;
 42     }
 43 
 44     public int readUnsignedByte() {
 45         int val = readUnsignedByteAt(offset);
 46         offset += 1;
 47         return val;
 48     }
 49 
 50     public int readUnsignedByteAt(int offset) {
 51         return data[offset++] & 0xff;
 52     }
 53 
 54     public int readUnsignedShort() {
 55         int val = readUnsignedShortAt(offset);
 56         offset += 2;
 57         return val;
 58     }
 59 
 60     public int readInt() {
 61         int val = readIntAt(offset);
 62         offset += 4;
 63         return val;
 64     }
 65 
 66     public int readUnsignedShortAt(int offset) {
 67         int b1 = data[offset++] & 0xff;
 68         int b2 = data[offset] & 0xff;
 69 
 70         return (b1 << 8) + b2;
 71     }
 72 
 73     public int readIntAt(int offset) {
 74         int s1 = readUnsignedShortAt(offset);
 75         int s2 = readUnsignedShortAt(offset + 2);
 76         return (s1 << 16) + s2;
 77     }
 78 
 79     public String readUtf8(int length) throws IllegalStateException {
 80         char str[] = new char[length];
 81         int count = 0;
 82         int pos = 0;
 83         while (count < length) {
 84             int c = readUnsignedByte();
 85             switch (c >> 4) {
 86                 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
 87                     // 0xxxxxxx
 88                     count++;
 89                     if(c == '/') {
 90                         str[pos++] = '.';
 91                     } else {
 92                         str[pos++] = (char) c;
 93                     }
 94                     break;
 95                 } case 12: case 13: {
 96                     // 110x xxxx   10xx xxxx
 97                     count += 2;
 98                     int c2 = readUnsignedByte();
 99                     if ((c2 & 0xC0) != 0x80) {
100                         throw new IllegalStateException();
101                     }
102                     str[pos++] = (char) (((c & 0x1F) << 6) | (c2 & 0x3F));
103                     break;
104                 } case 14: {
105                     // 1110 xxxx  10xx xxxx  10xx xxxx
106                     count += 3;
107                     int c2 = readUnsignedByte();
108                     int c3 = readUnsignedByte();
109                     if ((c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80) {
110                         throw new IllegalStateException();
111                     }
112                     str[pos++] = (char)(((c  & 0x0F) << 12) |
113                                         ((c2 & 0x3F) << 6)  |
114                                         ((c3 & 0x3F) << 0));
115                     break;
116                 } default:
117                     // 10xx xxxx,  1111 xxxx
118                     throw new IllegalStateException();
119             }
120         }
121         return new String(str);
122     }
123 }