1163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey/* 2163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * Copyright (C) 2011 The Android Open Source Project 3163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * 4163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * you may not use this file except in compliance with the License. 6163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * You may obtain a copy of the License at 7163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * 8163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * 10163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 11163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * See the License for the specific language governing permissions and 14163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * limitations under the License. 15163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey */ 16163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 17163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkeypackage com.android.internal.util; 18163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 19163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkeyimport java.io.Closeable; 20163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkeyimport java.io.IOException; 21163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkeyimport java.io.InputStream; 228e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkeyimport java.net.ProtocolException; 23d396a448b2e36e29598c954b64bfddef73f3fae0Elliott Hughesimport java.nio.charset.StandardCharsets; 24163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 25163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey/** 26163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * Reader that specializes in parsing {@code /proc/} files quickly. Walks 27163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * through the stream using a single space {@code ' '} as token separator, and 28163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * requires each line boundary to be explicitly acknowledged using 29d396a448b2e36e29598c954b64bfddef73f3fae0Elliott Hughes * {@link #finishLine()}. Assumes {@link StandardCharsets#US_ASCII} encoding. 30163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * <p> 31163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * Currently doesn't support formats based on {@code \0}, tabs, or repeated 32163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * delimiters. 33163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey */ 34163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkeypublic class ProcFileReader implements Closeable { 35163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey private final InputStream mStream; 36163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey private final byte[] mBuffer; 37163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 38163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey /** Write pointer in {@link #mBuffer}. */ 39163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey private int mTail; 40163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey /** Flag when last read token finished current line. */ 41163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey private boolean mLineFinished; 42163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 43163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey public ProcFileReader(InputStream stream) throws IOException { 44163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey this(stream, 4096); 45163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 46163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 47163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey public ProcFileReader(InputStream stream, int bufferSize) throws IOException { 48163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey mStream = stream; 49163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey mBuffer = new byte[bufferSize]; 50163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 51163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey // read enough to answer hasMoreData 52163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey fillBuf(); 53163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 54163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 55163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey /** 56163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * Read more data from {@link #mStream} into internal buffer. 57163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey */ 58163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey private int fillBuf() throws IOException { 59163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey final int length = mBuffer.length - mTail; 60163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey if (length == 0) { 61163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey throw new IOException("attempting to fill already-full buffer"); 62163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 63163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 64163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey final int read = mStream.read(mBuffer, mTail, length); 65163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey if (read != -1) { 66163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey mTail += read; 67163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 68163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey return read; 69163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 70163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 71163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey /** 72163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * Consume number of bytes from beginning of internal buffer. If consuming 73163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * all remaining bytes, will attempt to {@link #fillBuf()}. 74163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey */ 75163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey private void consumeBuf(int count) throws IOException { 76163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey // TODO: consider moving to read pointer, but for now traceview says 77163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey // these copies aren't a bottleneck. 78163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey System.arraycopy(mBuffer, count, mBuffer, 0, mTail - count); 79163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey mTail -= count; 80163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey if (mTail == 0) { 81163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey fillBuf(); 82163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 83163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 84163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 85163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey /** 868e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey * Find buffer index of next token delimiter, usually space or newline. 878e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey * Fills buffer as needed. 888e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey * 898e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey * @return Index of next delimeter, otherwise -1 if no tokens remain on 908e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey * current line. 91163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey */ 92163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey private int nextTokenIndex() throws IOException { 93163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey if (mLineFinished) { 948e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey return -1; 95163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 96163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 97163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey int i = 0; 98163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey do { 99163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey // scan forward for token boundary 100163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey for (; i < mTail; i++) { 101163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey final byte b = mBuffer[i]; 102163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey if (b == '\n') { 103163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey mLineFinished = true; 104163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey return i; 105163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 106163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey if (b == ' ') { 107163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey return i; 108163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 109163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 110163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } while (fillBuf() > 0); 111163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 1128e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey throw new ProtocolException("End of stream while looking for token boundary"); 113163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 114163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 115163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey /** 116163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * Check if stream has more data to be parsed. 117163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey */ 118163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey public boolean hasMoreData() { 119163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey return mTail > 0; 120163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 121163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 122163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey /** 123163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * Finish current line, skipping any remaining data. 124163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey */ 125163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey public void finishLine() throws IOException { 126163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey // last token already finished line; reset silently 127163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey if (mLineFinished) { 128163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey mLineFinished = false; 129163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey return; 130163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 131163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 132163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey int i = 0; 133163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey do { 134163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey // scan forward for line boundary and consume 135163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey for (; i < mTail; i++) { 136163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey if (mBuffer[i] == '\n') { 137163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey consumeBuf(i + 1); 138163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey return; 139163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 140163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 141163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } while (fillBuf() > 0); 142163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 1438e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey throw new ProtocolException("End of stream while looking for line boundary"); 144163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 145163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 146163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey /** 147163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * Parse and return next token as {@link String}. 148163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey */ 149163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey public String nextString() throws IOException { 150163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey final int tokenIndex = nextTokenIndex(); 1518e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey if (tokenIndex == -1) { 1528e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey throw new ProtocolException("Missing required string"); 1538e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey } else { 1548e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey return parseAndConsumeString(tokenIndex); 1558e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey } 156163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 157163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 158163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey /** 159163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * Parse and return next token as base-10 encoded {@code long}. 160163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey */ 161163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey public long nextLong() throws IOException { 162163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey final int tokenIndex = nextTokenIndex(); 1638e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey if (tokenIndex == -1) { 1648e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey throw new ProtocolException("Missing required long"); 1658e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey } else { 1668e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey return parseAndConsumeLong(tokenIndex); 1678e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey } 1688e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey } 1698e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey 1708e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey /** 1718e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey * Parse and return next token as base-10 encoded {@code long}, or return 1728e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey * the given default value if no remaining tokens on current line. 1738e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey */ 1748e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey public long nextOptionalLong(long def) throws IOException { 1758e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey final int tokenIndex = nextTokenIndex(); 1768e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey if (tokenIndex == -1) { 1778e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey return def; 1788e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey } else { 1798e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey return parseAndConsumeLong(tokenIndex); 1808e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey } 1818e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey } 1828e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey 1838e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey private String parseAndConsumeString(int tokenIndex) throws IOException { 184a920f25fe55fc9afc7640902a200f19ce278588bElliott Hughes final String s = new String(mBuffer, 0, tokenIndex, StandardCharsets.US_ASCII); 1858e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey consumeBuf(tokenIndex + 1); 1868e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey return s; 1878e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey } 1888e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey 1898e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey private long parseAndConsumeLong(int tokenIndex) throws IOException { 190163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey final boolean negative = mBuffer[0] == '-'; 191163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 192163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey // TODO: refactor into something like IntegralToString 193163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey long result = 0; 194163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey for (int i = negative ? 1 : 0; i < tokenIndex; i++) { 195163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey final int digit = mBuffer[i] - '0'; 196163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey if (digit < 0 || digit > 9) { 197163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey throw invalidLong(tokenIndex); 198163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 199163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 200163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey // always parse as negative number and apply sign later; this 201163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey // correctly handles MIN_VALUE which is "larger" than MAX_VALUE. 202163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey final long next = result * 10 - digit; 203163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey if (next > result) { 204163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey throw invalidLong(tokenIndex); 205163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 206163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey result = next; 207163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 208163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 209163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey consumeBuf(tokenIndex + 1); 210163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey return negative ? result : -result; 211163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 212163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 213163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey private NumberFormatException invalidLong(int tokenIndex) { 214163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey return new NumberFormatException( 215d396a448b2e36e29598c954b64bfddef73f3fae0Elliott Hughes "invalid long: " + new String(mBuffer, 0, tokenIndex, StandardCharsets.US_ASCII)); 216163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 217163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 218163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey /** 219163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey * Parse and return next token as base-10 encoded {@code int}. 220163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey */ 221163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey public int nextInt() throws IOException { 222163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey final long value = nextLong(); 223163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) { 224163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey throw new NumberFormatException("parsed value larger than integer"); 225163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 226163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey return (int) value; 227163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 228163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey 2298e7b3b15f7a4f888d55f080d3ed61860cd5fab55Jeff Sharkey @Override 230163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey public void close() throws IOException { 231163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey mStream.close(); 232163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey } 233163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey} 234