| /* ==================================================================== |
| 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.hemf.record.emfplus; |
| |
| import java.io.IOException; |
| import java.util.Iterator; |
| import java.util.NoSuchElementException; |
| |
| import org.apache.poi.util.LittleEndianInputStream; |
| import org.apache.poi.util.RecordFormatException; |
| |
| public class HemfPlusRecordIterator implements Iterator<HemfPlusRecord> { |
| |
| private final LittleEndianInputStream leis; |
| private final int startIdx; |
| private final int limit; |
| private HemfPlusRecord currentRecord; |
| |
| public HemfPlusRecordIterator(LittleEndianInputStream leis) { |
| this(leis, -1); |
| } |
| |
| public HemfPlusRecordIterator(LittleEndianInputStream leis, int limit) { |
| this.leis = leis; |
| this.limit = limit; |
| startIdx = leis.getReadIndex(); |
| //queue the first non-header record |
| currentRecord = _next(); |
| } |
| |
| @Override |
| public boolean hasNext() { |
| return currentRecord != null; |
| } |
| |
| @Override |
| public HemfPlusRecord next() { |
| if (!hasNext()) { |
| throw new NoSuchElementException(); |
| } |
| HemfPlusRecord toReturn = currentRecord; |
| // add the size for recordId/flags/recordSize/dataSize = 12 bytes |
| final boolean isEOF = (limit == -1 || (leis.getReadIndex()-startIdx)+12 > limit); |
| currentRecord = isEOF ? null : _next(); |
| return toReturn; |
| } |
| |
| private HemfPlusRecord _next() { |
| if (currentRecord != null && HemfPlusRecordType.eof == currentRecord.getEmfPlusRecordType()) { |
| return null; |
| } |
| // A 16-bit unsigned integer that identifies this record type |
| int recordId = leis.readUShort(); |
| // A 16-bit unsigned integer that provides information about how the operation is |
| // to be performed, and about the structure of the record. |
| int flags = leis.readUShort(); |
| // A 32-bit unsigned integer that specifies the 32-bit-aligned size of the entire |
| // record in bytes, including the 12-byte record header and record-specific data. |
| int recordSize = (int)leis.readUInt(); |
| // A 32-bit unsigned integer that specifies the 32-bit-aligned number of bytes of data |
| // in the record-specific data that follows. This number does not include the size of |
| // the invariant part of this record. |
| int dataSize = (int)leis.readUInt(); |
| |
| HemfPlusRecordType type = HemfPlusRecordType.getById(recordId); |
| if (type == null) { |
| throw new RecordFormatException("Undefined record of type:"+recordId); |
| } |
| final HemfPlusRecord record = type.constructor.get(); |
| |
| try { |
| long readBytes = record.init(leis, dataSize, recordId, flags); |
| assert (readBytes <= recordSize-12); |
| leis.skipFully((int)(recordSize-12-readBytes)); |
| } catch (IOException e) { |
| throw new RecordFormatException(e); |
| } |
| |
| return record; |
| } |
| |
| @Override |
| public void remove() { |
| throw new UnsupportedOperationException("Remove not supported"); |
| } |
| |
| } |