View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.giraph.utils;
20  
21  import java.io.IOException;
22  import java.io.UTFDataFormatException;
23  
24  /**
25   * Byte array input stream that uses Unsafe methods to deserialize
26   * much faster
27   */
28  public abstract class UnsafeReads implements ExtendedDataInput {
29  
30    /** Buffer length */
31    protected int bufLength;
32    /** Position in the buffer */
33    protected long pos = 0;
34  
35    /**
36     * Constructor
37     *
38     * @param length buf length
39     */
40    public UnsafeReads(int length) {
41      bufLength = length;
42    }
43  
44    /**
45     * Constructor with offset
46     *
47     * @param offset offset in memory
48     * @param length buf length
49     */
50    public UnsafeReads(long offset, int length) {
51      pos = offset;
52      bufLength = length;
53    }
54  
55    /**
56     * How many bytes are still available?
57     *
58     * @return Number of bytes available
59     */
60    public abstract int available();
61  
62    /**
63     * What position in the stream?
64     *
65     * @return Position
66     */
67    public abstract int getPos();
68  
69    /**
70     * Check whether there are enough remaining bytes for an operation
71     *
72     * @param requiredBytes Bytes required to read
73     * @throws IOException When there are not enough bytes to read
74     */
75    protected void ensureRemaining(int requiredBytes) throws IOException {
76      if (available() < requiredBytes) {
77        throw new IOException("ensureRemaining: Only " + available() +
78            " bytes remaining, trying to read " + requiredBytes);
79      }
80    }
81  
82    @Override
83    public int skipBytes(int n) throws IOException {
84      ensureRemaining(n);
85      pos += n;
86      return n;
87    }
88  
89    @Override
90    public String readLine() throws IOException {
91      // Note that this code is mostly copied from DataInputStream
92      char[] tmpBuf = new char[128];
93  
94      int room = tmpBuf.length;
95      int offset = 0;
96      int c;
97  
98    loop:
99      while (true) {
100       c = readByte();
101       switch (c) {
102       case -1:
103       case '\n':
104         break loop;
105       case '\r':
106         int c2 = readByte();
107         if ((c2 != '\n') && (c2 != -1)) {
108           pos -= 1;
109         }
110         break loop;
111       default:
112         if (--room < 0) {
113           char[] replacebuf = new char[offset + 128];
114           room = replacebuf.length - offset - 1;
115           System.arraycopy(tmpBuf, 0, replacebuf, 0, offset);
116           tmpBuf = replacebuf;
117         }
118         tmpBuf[offset++] = (char) c;
119         break;
120       }
121     }
122     if ((c == -1) && (offset == 0)) {
123       return null;
124     }
125     return String.copyValueOf(tmpBuf, 0, offset);
126   }
127 
128   @Override
129   public String readUTF() throws IOException {
130     // Note that this code is mostly copied from DataInputStream
131     int utflen = readUnsignedShort();
132 
133     byte[] bytearr = new byte[utflen];
134     char[] chararr = new char[utflen];
135 
136     int c;
137     int char2;
138     int char3;
139     int count = 0;
140     int chararrCount = 0;
141 
142     readFully(bytearr, 0, utflen);
143 
144     while (count < utflen) {
145       c = (int) bytearr[count] & 0xff;
146       if (c > 127) {
147         break;
148       }
149       count++;
150       chararr[chararrCount++] = (char) c;
151     }
152 
153     while (count < utflen) {
154       c = (int) bytearr[count] & 0xff;
155       switch (c >> 4) {
156       case 0:
157       case 1:
158       case 2:
159       case 3:
160       case 4:
161       case 5:
162       case 6:
163       case 7:
164       /* 0xxxxxxx */
165         count++;
166         chararr[chararrCount++] = (char) c;
167         break;
168       case 12:
169       case 13:
170       /* 110x xxxx   10xx xxxx*/
171         count += 2;
172         if (count > utflen) {
173           throw new UTFDataFormatException(
174               "malformed input: partial character at end");
175         }
176         char2 = (int) bytearr[count - 1];
177         if ((char2 & 0xC0) != 0x80) {
178           throw new UTFDataFormatException(
179               "malformed input around byte " + count);
180         }
181         chararr[chararrCount++] = (char) (((c & 0x1F) << 6) |
182             (char2 & 0x3F));
183         break;
184       case 14:
185       /* 1110 xxxx  10xx xxxx  10xx xxxx */
186         count += 3;
187         if (count > utflen) {
188           throw new UTFDataFormatException(
189               "malformed input: partial character at end");
190         }
191         char2 = (int) bytearr[count - 2];
192         char3 = (int) bytearr[count - 1];
193         if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) {
194           throw new UTFDataFormatException(
195               "malformed input around byte " + (count - 1));
196         }
197         chararr[chararrCount++] = (char) (((c & 0x0F) << 12) |
198             ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
199         break;
200       default:
201       /* 10xx xxxx,  1111 xxxx */
202         throw new UTFDataFormatException(
203             "malformed input around byte " + count);
204       }
205     }
206     // The number of chars produced may be less than utflen
207     return new String(chararr, 0, chararrCount);
208   }
209 }