| /* |
| * ==================================================================== |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * ==================================================================== |
| */ |
| |
| package org.apache.poi.hssf.record.cont; |
| |
| import org.apache.poi.hssf.record.ContinueRecord; |
| import org.apache.poi.hssf.record.RecordInputStream; |
| import org.apache.poi.util.LittleEndianInput; |
| |
| /** |
| * A decorated {@link RecordInputStream} that can read primitive data types |
| * (short, int, long, etc.) spanned across a {@link ContinueRecord } boundary. |
| * |
| * <p> |
| * Most records construct themselves from {@link RecordInputStream}. |
| * This class assumes that a {@link ContinueRecord} record break always occurs at the type boundary, |
| * however, it is not always so. |
| * </p> |
| * Two attachments to <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=50779">Bugzilla 50779</a> |
| * demonstrate that a CONTINUE break can appear right in between two bytes of a unicode character |
| * or between two bytes of a <code>short</code>. The problematic portion of the data is |
| * in a Asian Phonetic Settings Block (ExtRst) of a UnicodeString. |
| * <p> |
| * {@link RecordInputStream} greedily requests the bytes to be read and stumbles on such files with a |
| * "Not enough data (1) to read requested (2) bytes" exception. The <code>ContinuableRecordInput</code> |
| * class circumvents this "type boundary" rule and reads data byte-by-byte rolling over CONTINUE if necessary. |
| * </p> |
| * |
| * <p> |
| * YK: For now (March 2011) this class is only used to read |
| * @see org.apache.poi.hssf.record.common.ExtRst blocks of a UnicodeString. |
| * |
| * </p> |
| */ |
| public class ContinuableRecordInput implements LittleEndianInput { |
| private final RecordInputStream _in; |
| |
| public ContinuableRecordInput(RecordInputStream in){ |
| _in = in; |
| } |
| @Override |
| public int available(){ |
| return _in.available(); |
| } |
| |
| @Override |
| public byte readByte(){ |
| return _in.readByte(); |
| } |
| |
| @Override |
| public int readUByte(){ |
| return _in.readUByte(); |
| } |
| |
| @Override |
| public short readShort(){ |
| return _in.readShort(); |
| } |
| |
| @Override |
| public int readUShort(){ |
| int ch1 = readUByte(); |
| int ch2 = readUByte(); |
| return (ch2 << 8) + (ch1); |
| } |
| |
| @Override |
| public int readInt(){ |
| int ch1 = _in.readUByte(); |
| int ch2 = _in.readUByte(); |
| int ch3 = _in.readUByte(); |
| int ch4 = _in.readUByte(); |
| return (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1); |
| } |
| |
| @Override |
| public long readLong(){ |
| int b0 = _in.readUByte(); |
| int b1 = _in.readUByte(); |
| int b2 = _in.readUByte(); |
| int b3 = _in.readUByte(); |
| int b4 = _in.readUByte(); |
| int b5 = _in.readUByte(); |
| int b6 = _in.readUByte(); |
| int b7 = _in.readUByte(); |
| return (((long)b7 << 56) + |
| ((long)b6 << 48) + |
| ((long)b5 << 40) + |
| ((long)b4 << 32) + |
| ((long)b3 << 24) + |
| (b2 << 16) + |
| (b1 << 8) + |
| (b0)); |
| } |
| |
| @Override |
| public double readDouble(){ |
| return _in.readDouble(); |
| } |
| |
| @Override |
| public void readFully(byte[] buf){ |
| _in.readFully(buf); |
| } |
| |
| @Override |
| public void readFully(byte[] buf, int off, int len){ |
| _in.readFully(buf, off, len); |
| } |
| |
| @Override |
| public void readPlain(byte[] buf, int off, int len) { |
| readFully(buf, off, len); |
| } |
| } |