| /* ==================================================================== |
| 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.hwpf.sprm; |
| |
| import java.util.Arrays; |
| |
| import org.apache.poi.util.Internal; |
| import org.apache.poi.util.LittleEndian; |
| |
| @Internal |
| public final class SprmBuffer implements Cloneable |
| { |
| byte[] _buf; |
| boolean _istd; |
| int _offset; |
| |
| private final int _sprmsStartOffset; |
| |
| /** |
| * @deprecated Use {@link #SprmBuffer(int)} instead |
| */ |
| @Deprecated |
| public SprmBuffer() |
| { |
| this( 0 ); |
| } |
| |
| /** |
| * @deprecated Use {@link #SprmBuffer(byte[],int)} instead |
| */ |
| @Deprecated |
| public SprmBuffer( byte[] buf ) |
| { |
| this( buf, 0 ); |
| } |
| |
| /** |
| * @deprecated Use {@link #SprmBuffer(byte[],boolean,int)} instead |
| */ |
| @Deprecated |
| public SprmBuffer( byte[] buf, boolean istd ) |
| { |
| this( buf, istd, 0 ); |
| } |
| |
| public SprmBuffer( byte[] buf, boolean istd, int sprmsStartOffset ) |
| { |
| _offset = buf.length; |
| _buf = buf; |
| _istd = istd; |
| _sprmsStartOffset = sprmsStartOffset; |
| } |
| |
| public SprmBuffer( byte[] buf, int _sprmsStartOffset ) |
| { |
| this( buf, false, _sprmsStartOffset ); |
| } |
| |
| public SprmBuffer( int sprmsStartOffset ) |
| { |
| _buf = new byte[sprmsStartOffset + 4]; |
| _offset = sprmsStartOffset; |
| _sprmsStartOffset = sprmsStartOffset; |
| } |
| |
| public void addSprm(short opcode, byte operand) |
| { |
| int addition = LittleEndian.SHORT_SIZE + LittleEndian.BYTE_SIZE; |
| ensureCapacity(addition); |
| LittleEndian.putShort(_buf, _offset, opcode); |
| _offset += LittleEndian.SHORT_SIZE; |
| _buf[_offset++] = operand; |
| } |
| |
| public void addSprm(short opcode, byte[] operand) |
| { |
| int addition = LittleEndian.SHORT_SIZE + LittleEndian.BYTE_SIZE + operand.length; |
| ensureCapacity(addition); |
| LittleEndian.putShort(_buf, _offset, opcode); |
| _offset += LittleEndian.SHORT_SIZE; |
| _buf[_offset++] = (byte)operand.length; |
| System.arraycopy(operand, 0, _buf, _offset, operand.length); |
| } |
| |
| public void addSprm(short opcode, int operand) |
| { |
| int addition = LittleEndian.SHORT_SIZE + LittleEndian.INT_SIZE; |
| ensureCapacity(addition); |
| LittleEndian.putShort(_buf, _offset, opcode); |
| _offset += LittleEndian.SHORT_SIZE; |
| LittleEndian.putInt(_buf, _offset, operand); |
| _offset += LittleEndian.INT_SIZE; |
| } |
| |
| public void addSprm(short opcode, short operand) |
| { |
| int addition = LittleEndian.SHORT_SIZE + LittleEndian.SHORT_SIZE; |
| ensureCapacity(addition); |
| LittleEndian.putShort(_buf, _offset, opcode); |
| _offset += LittleEndian.SHORT_SIZE; |
| LittleEndian.putShort(_buf, _offset, operand); |
| _offset += LittleEndian.SHORT_SIZE; |
| } |
| |
| public void append( byte[] grpprl ) |
| { |
| append( grpprl, 0 ); |
| } |
| |
| public void append( byte[] grpprl, int offset ) |
| { |
| ensureCapacity( grpprl.length - offset ); |
| System.arraycopy( grpprl, offset, _buf, _offset, grpprl.length - offset ); |
| _offset += grpprl.length - offset; |
| } |
| public SprmBuffer clone() |
| { |
| try { |
| SprmBuffer retVal = (SprmBuffer)super.clone(); |
| retVal._buf = new byte[_buf.length]; |
| System.arraycopy(_buf, 0, retVal._buf, 0, _buf.length); |
| return retVal; |
| } catch (CloneNotSupportedException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| private void ensureCapacity( int addition ) |
| { |
| if ( _offset + addition >= _buf.length ) |
| { |
| // add 6 more than they need for use the next iteration |
| // |
| // commented - buffer shall not contain any additional bytes -- |
| // sergey |
| // byte[] newBuf = new byte[_offset + addition + 6]; |
| byte[] newBuf = new byte[_offset + addition]; |
| System.arraycopy( _buf, 0, newBuf, 0, _buf.length ); |
| _buf = newBuf; |
| } |
| } |
| |
| @Override |
| public boolean equals(Object obj) |
| { |
| if (!(obj instanceof SprmBuffer)) return false; |
| SprmBuffer sprmBuf = (SprmBuffer)obj; |
| return (Arrays.equals(_buf, sprmBuf._buf)); |
| } |
| |
| @Override |
| public int hashCode() { |
| assert false : "hashCode not designed"; |
| return 42; // any arbitrary constant will do |
| } |
| |
| public SprmOperation findSprm( short opcode ) |
| { |
| int operation = SprmOperation.getOperationFromOpcode( opcode ); |
| int type = SprmOperation.getTypeFromOpcode( opcode ); |
| |
| SprmIterator si = new SprmIterator( _buf, 2 ); |
| while ( si.hasNext() ) |
| { |
| SprmOperation i = si.next(); |
| if ( i.getOperation() == operation && i.getType() == type ) |
| return i; |
| } |
| return null; |
| } |
| |
| private int findSprmOffset( short opcode ) |
| { |
| SprmOperation sprmOperation = findSprm( opcode ); |
| if ( sprmOperation == null ) |
| return -1; |
| |
| return sprmOperation.getGrpprlOffset(); |
| } |
| |
| public byte[] toByteArray() |
| { |
| return _buf; |
| } |
| |
| public SprmIterator iterator() |
| { |
| return new SprmIterator( _buf, _sprmsStartOffset ); |
| } |
| |
| public void updateSprm(short opcode, byte operand) |
| { |
| int grpprlOffset = findSprmOffset(opcode); |
| if(grpprlOffset != -1) |
| { |
| _buf[grpprlOffset] = operand; |
| return; |
| } |
| addSprm(opcode, operand); |
| } |
| |
| public void updateSprm( short opcode, boolean operand ) |
| { |
| int grpprlOffset = findSprmOffset( opcode ); |
| if ( grpprlOffset != -1 ) |
| { |
| _buf[grpprlOffset] = (byte) ( operand ? 1 : 0 ); |
| return; |
| } |
| addSprm( opcode, operand ? 1 : 0 ); |
| } |
| |
| public void updateSprm(short opcode, int operand) |
| { |
| int grpprlOffset = findSprmOffset(opcode); |
| if(grpprlOffset != -1) |
| { |
| LittleEndian.putInt(_buf, grpprlOffset, operand); |
| return; |
| } |
| addSprm(opcode, operand); |
| } |
| |
| public void updateSprm(short opcode, short operand) |
| { |
| int grpprlOffset = findSprmOffset(opcode); |
| if(grpprlOffset != -1) |
| { |
| LittleEndian.putShort(_buf, grpprlOffset, operand); |
| return; |
| } |
| addSprm(opcode, operand); |
| } |
| |
| @Override |
| public String toString() |
| { |
| StringBuilder stringBuilder = new StringBuilder(); |
| stringBuilder.append( "Sprms (" ); |
| stringBuilder.append( _buf.length ); |
| stringBuilder.append( " byte(s)): " ); |
| for ( SprmIterator iterator = iterator(); iterator.hasNext(); ) |
| { |
| try |
| { |
| stringBuilder.append( iterator.next() ); |
| } |
| catch ( Exception exc ) |
| { |
| stringBuilder.append( "error" ); |
| } |
| stringBuilder.append( "; " ); |
| } |
| return stringBuilder.toString(); |
| } |
| } |