Remove unnecessary cast and reformat some code a bit

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1771247 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Dominik Stadler 2016-11-25 05:34:58 +00:00
parent f656e74c4b
commit f2975b1e5f
7 changed files with 376 additions and 461 deletions

View File

@ -32,7 +32,7 @@ public class WorkingWithRichText {
XSSFWorkbook wb = new XSSFWorkbook(); //or new HSSFWorkbook(); XSSFWorkbook wb = new XSSFWorkbook(); //or new HSSFWorkbook();
try { try {
XSSFSheet sheet = wb.createSheet(); XSSFSheet sheet = wb.createSheet();
XSSFRow row = sheet.createRow((short) 2); XSSFRow row = sheet.createRow(2);
XSSFCell cell = row.createCell(1); XSSFCell cell = row.createCell(1);
XSSFRichTextString rt = new XSSFRichTextString("The quick brown fox"); XSSFRichTextString rt = new XSSFRichTextString("The quick brown fox");
@ -53,7 +53,7 @@ public class WorkingWithRichText {
rt.append(" Jumped over the lazy dog", font3); rt.append(" Jumped over the lazy dog", font3);
cell.setCellValue(rt); cell.setCellValue(rt);
// Write the output to a file // Write the output to a file
OutputStream fileOut = new FileOutputStream("xssf-richtext.xlsx"); OutputStream fileOut = new FileOutputStream("xssf-richtext.xlsx");
try { try {

View File

@ -28,78 +28,68 @@ import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
@Internal @Internal
public final class ComplexFileTable public final class ComplexFileTable {
{ private static final byte GRPPRL_TYPE = 1;
private static final byte TEXT_PIECE_TABLE_TYPE = 2;
private static final byte GRPPRL_TYPE = 1; protected TextPieceTable _tpt;
private static final byte TEXT_PIECE_TABLE_TYPE = 2;
protected TextPieceTable _tpt; private SprmBuffer[] _grpprls;
private SprmBuffer[] _grpprls; public ComplexFileTable() {
_tpt = new TextPieceTable();
public ComplexFileTable() }
{
_tpt = new TextPieceTable();
}
public ComplexFileTable(byte[] documentStream, byte[] tableStream, int offset, int fcMin) throws IOException public ComplexFileTable(byte[] documentStream, byte[] tableStream, int offset, int fcMin) throws IOException {
{ //skips through the prms before we reach the piece table. These contain data
//skips through the prms before we reach the piece table. These contain data //for actual fast saved files
//for actual fast saved files
List<SprmBuffer> sprmBuffers = new LinkedList<SprmBuffer>(); List<SprmBuffer> sprmBuffers = new LinkedList<SprmBuffer>();
while ( tableStream[offset] == GRPPRL_TYPE ) while (tableStream[offset] == GRPPRL_TYPE) {
{
offset++; offset++;
int size = LittleEndian.getShort( tableStream, offset ); int size = LittleEndian.getShort(tableStream, offset);
offset += LittleEndian.SHORT_SIZE; offset += LittleEndian.SHORT_SIZE;
byte[] bs = LittleEndian.getByteArray( tableStream, offset, size ); byte[] bs = LittleEndian.getByteArray(tableStream, offset, size);
offset += size; offset += size;
SprmBuffer sprmBuffer = new SprmBuffer( bs, false, 0 ); SprmBuffer sprmBuffer = new SprmBuffer(bs, false, 0);
sprmBuffers.add( sprmBuffer ); sprmBuffers.add(sprmBuffer);
} }
this._grpprls = sprmBuffers.toArray( new SprmBuffer[sprmBuffers.size()] ); this._grpprls = sprmBuffers.toArray(new SprmBuffer[sprmBuffers.size()]);
if(tableStream[offset] != TEXT_PIECE_TABLE_TYPE) if (tableStream[offset] != TEXT_PIECE_TABLE_TYPE) {
{ throw new IOException("The text piece table is corrupted");
throw new IOException("The text piece table is corrupted"); }
int pieceTableSize = LittleEndian.getInt(tableStream, ++offset);
offset += LittleEndian.INT_SIZE;
_tpt = new TextPieceTable(documentStream, tableStream, offset, pieceTableSize, fcMin);
} }
int pieceTableSize = LittleEndian.getInt(tableStream, ++offset);
offset += LittleEndian.INT_SIZE;
_tpt = new TextPieceTable(documentStream, tableStream, offset, pieceTableSize, fcMin);
}
public TextPieceTable getTextPieceTable() public TextPieceTable getTextPieceTable() {
{ return _tpt;
return _tpt; }
}
public SprmBuffer[] getGrpprls() public SprmBuffer[] getGrpprls() {
{
return _grpprls; return _grpprls;
} }
@Deprecated @Deprecated
public void writeTo( HWPFFileSystem sys ) throws IOException public void writeTo(HWPFFileSystem sys) throws IOException {
{ HWPFOutputStream docStream = sys.getStream("WordDocument");
HWPFOutputStream docStream = sys.getStream( "WordDocument" ); HWPFOutputStream tableStream = sys.getStream("1Table");
HWPFOutputStream tableStream = sys.getStream( "1Table" );
writeTo( docStream, tableStream ); writeTo(docStream, tableStream);
} }
public void writeTo( HWPFOutputStream wordDocumentStream, public void writeTo(HWPFOutputStream wordDocumentStream,
HWPFOutputStream tableStream ) throws IOException HWPFOutputStream tableStream) throws IOException {
{ tableStream.write(TEXT_PIECE_TABLE_TYPE);
tableStream.write( TEXT_PIECE_TABLE_TYPE );
byte[] table = _tpt.writeTo( wordDocumentStream ); byte[] table = _tpt.writeTo(wordDocumentStream);
byte[] numHolder = new byte[LittleEndian.INT_SIZE]; byte[] numHolder = new byte[LittleEndian.INT_SIZE];
LittleEndian.putInt( numHolder, 0, table.length ); LittleEndian.putInt(numHolder, 0, table.length);
tableStream.write( numHolder ); tableStream.write(numHolder);
tableStream.write( table ); tableStream.write(table);
} }
} }

View File

@ -41,27 +41,23 @@ import org.apache.poi.util.LittleEndian;
* @author Ryan Ackley * @author Ryan Ackley
*/ */
@Internal @Internal
public abstract class FormattedDiskPage public abstract class FormattedDiskPage {
{
protected byte[] _fkp; protected byte[] _fkp;
protected int _crun; protected int _crun;
protected int _offset; protected int _offset;
public FormattedDiskPage() {
public FormattedDiskPage()
{
} }
/** /**
* Uses a 512-byte array to create a FKP * Uses a 512-byte array to create a FKP
*/ */
public FormattedDiskPage(byte[] documentStream, int offset) public FormattedDiskPage(byte[] documentStream, int offset) {
{
_crun = LittleEndian.getUByte(documentStream, offset + 511); _crun = LittleEndian.getUByte(documentStream, offset + 511);
_fkp = documentStream; _fkp = documentStream;
_offset = offset; _offset = offset;
} }
/** /**
* Used to get a text offset corresponding to a grpprl in this fkp. * Used to get a text offset corresponding to a grpprl in this fkp.
* @param index The index of the property in this FKP * @param index The index of the property in this FKP
@ -71,6 +67,7 @@ public abstract class FormattedDiskPage
{ {
return LittleEndian.getInt(_fkp, _offset + (index * 4)); return LittleEndian.getInt(_fkp, _offset + (index * 4));
} }
/** /**
* Used to get the end of the text corresponding to a grpprl in this fkp. * Used to get the end of the text corresponding to a grpprl in this fkp.
* @param index The index of the property in this fkp. * @param index The index of the property in this fkp.
@ -80,6 +77,7 @@ public abstract class FormattedDiskPage
{ {
return LittleEndian.getInt(_fkp, _offset + ((index + 1) * 4)); return LittleEndian.getInt(_fkp, _offset + ((index + 1) * 4));
} }
/** /**
* Used to get the total number of grrprl's stored int this FKP * Used to get the total number of grrprl's stored int this FKP
* @return The number of grpprls in this FKP * @return The number of grpprls in this FKP

View File

@ -25,178 +25,148 @@ import org.apache.poi.util.LittleEndian;
/** /**
* Plex of CPs stored in File (PLCF) * Plex of CPs stored in File (PLCF)
* * <p>
* common data structure in a Word file. Contains an array of 4 byte ints in the * common data structure in a Word file. Contains an array of 4 byte ints in the
* front that relate to an array of arbitrary data structures in the back. * front that relate to an array of arbitrary data structures in the back.
* * <p>
* See page 184 of official documentation for details * See page 184 of official documentation for details
* *
* @author Ryan Ackley * @author Ryan Ackley
*/ */
public final class PlexOfCps public final class PlexOfCps {
{
private int _iMac; private int _iMac;
private int _offset; private int _offset;
private int _cbStruct; private int _cbStruct;
private List<GenericPropertyNode> _props; private List<GenericPropertyNode> _props;
public PlexOfCps( int sizeOfStruct ) public PlexOfCps(int sizeOfStruct) {
{
_props = new ArrayList<GenericPropertyNode>(); _props = new ArrayList<GenericPropertyNode>();
_cbStruct = sizeOfStruct; _cbStruct = sizeOfStruct;
} }
/** /**
* Constructor * Constructor
* *
* @param cb * @param cb The size of PLCF in bytes
* The size of PLCF in bytes * @param cbStruct The size of the data structure type stored in this PlexOfCps.
* @param cbStruct
* The size of the data structure type stored in this PlexOfCps.
*/ */
public PlexOfCps( byte[] buf, int start, int cb, int cbStruct ) public PlexOfCps(byte[] buf, int start, int cb, int cbStruct) {
{
// Figure out the number we hold // Figure out the number we hold
_iMac = ( cb - 4 ) / ( 4 + cbStruct ); _iMac = (cb - 4) / (4 + cbStruct);
_cbStruct = cbStruct; _cbStruct = cbStruct;
_props = new ArrayList<GenericPropertyNode>( _iMac ); _props = new ArrayList<GenericPropertyNode>(_iMac);
for ( int x = 0; x < _iMac; x++ ) for (int x = 0; x < _iMac; x++) {
{ _props.add(getProperty(x, buf, start));
_props.add( getProperty( x, buf, start ) );
} }
} }
@Internal @Internal
void adjust( int startCp, int shift ) void adjust(int startCp, int shift) {
{ for (GenericPropertyNode node : _props) {
for ( GenericPropertyNode node : _props ) if (node.getStart() > startCp) {
{ if (node.getStart() + shift < startCp) {
if ( node.getStart() > startCp ) node.setStart(startCp);
{ } else {
if ( node.getStart() + shift < startCp ) node.setStart(node.getStart() + shift);
{
node.setStart( startCp );
}
else
{
node.setStart( node.getStart() + shift );
} }
} }
if ( node.getEnd() >= startCp ) if (node.getEnd() >= startCp) {
{ if (node.getEnd() + shift < startCp) {
if ( node.getEnd() + shift < startCp ) node.setEnd(startCp);
{ } else {
node.setEnd( startCp ); node.setEnd(node.getEnd() + shift);
}
else
{
node.setEnd( node.getEnd() + shift );
} }
} }
} }
} }
public GenericPropertyNode getProperty( int index ) public GenericPropertyNode getProperty(int index) {
{ return _props.get(index);
return _props.get( index );
} }
public void addProperty( GenericPropertyNode node ) public void addProperty(GenericPropertyNode node) {
{ _props.add(node);
_props.add( node );
_iMac++; _iMac++;
} }
void remove( int index ) void remove(int index) {
{ _props.remove(index);
_props.remove( index );
_iMac--; _iMac--;
} }
public byte[] toByteArray() public byte[] toByteArray() {
{
int size = _props.size(); int size = _props.size();
int cpBufSize = ( ( size + 1 ) * LittleEndian.INT_SIZE ); int cpBufSize = ((size + 1) * LittleEndian.INT_SIZE);
int structBufSize = +( _cbStruct * size ); int structBufSize = +(_cbStruct * size);
int bufSize = cpBufSize + structBufSize; int bufSize = cpBufSize + structBufSize;
byte[] buf = new byte[bufSize]; byte[] buf = new byte[bufSize];
GenericPropertyNode node = null; GenericPropertyNode node = null;
for ( int x = 0; x < size; x++ ) for (int x = 0; x < size; x++) {
{ node = _props.get(x);
node = _props.get( x );
// put the starting offset of the property into the plcf. // put the starting offset of the property into the plcf.
LittleEndian.putInt( buf, ( LittleEndian.INT_SIZE * x ), LittleEndian.putInt(buf, (LittleEndian.INT_SIZE * x),
node.getStart() ); node.getStart());
// put the struct into the plcf // put the struct into the plcf
System.arraycopy( node.getBytes(), 0, buf, cpBufSize System.arraycopy(node.getBytes(), 0, buf, cpBufSize
+ ( x * _cbStruct ), _cbStruct ); + (x * _cbStruct), _cbStruct);
} }
// put the ending offset of the last property into the plcf. // put the ending offset of the last property into the plcf.
LittleEndian.putInt( buf, LittleEndian.INT_SIZE * size, node.getEnd() ); LittleEndian.putInt(buf, LittleEndian.INT_SIZE * size, node.getEnd());
return buf; return buf;
} }
private GenericPropertyNode getProperty( int index, byte[] buf, int offset ) private GenericPropertyNode getProperty(int index, byte[] buf, int offset) {
{ int start = LittleEndian.getInt(buf, offset + getIntOffset(index));
int start = LittleEndian.getInt( buf, offset + getIntOffset( index ) ); int end = LittleEndian.getInt(buf, offset + getIntOffset(index + 1));
int end = LittleEndian.getInt( buf, offset + getIntOffset( index + 1 ) );
byte[] struct = new byte[_cbStruct]; byte[] struct = new byte[_cbStruct];
System.arraycopy( buf, offset + getStructOffset( index ), struct, 0, System.arraycopy(buf, offset + getStructOffset(index), struct, 0,
_cbStruct ); _cbStruct);
return new GenericPropertyNode( start, end, struct ); return new GenericPropertyNode(start, end, struct);
} }
private int getIntOffset( int index ) private int getIntOffset(int index) {
{
return index * 4; return index * 4;
} }
/** /**
* returns the number of data structures in this PlexofCps. * returns the number of data structures in this PlexofCps.
* *
* @return The number of data structures in this PlexofCps * @return The number of data structures in this PlexofCps
*/ */
public int length() public int length() {
{
return _iMac; return _iMac;
} }
/** /**
* Returns the offset, in bytes, from the beginning if this PlexOfCps to the * Returns the offset, in bytes, from the beginning if this PlexOfCps to the
* data structure at index. * data structure at index.
* *
* @param index * @param index The index of the data structure.
* The index of the data structure.
*
* @return The offset, in bytes, from the beginning if this PlexOfCps to the * @return The offset, in bytes, from the beginning if this PlexOfCps to the
* data structure at index. * data structure at index.
*/ */
private int getStructOffset( int index ) private int getStructOffset(int index) {
{ return (4 * (_iMac + 1)) + (_cbStruct * index);
return ( 4 * ( _iMac + 1 ) ) + ( _cbStruct * index );
} }
GenericPropertyNode[] toPropertiesArray() GenericPropertyNode[] toPropertiesArray() {
{ if (_props == null || _props.isEmpty())
if ( _props == null || _props.isEmpty() )
return new GenericPropertyNode[0]; return new GenericPropertyNode[0];
return _props.toArray( new GenericPropertyNode[_props.size()] ); return _props.toArray(new GenericPropertyNode[_props.size()]);
} }
@Override @Override
public String toString() public String toString() {
{
return "PLCF (cbStruct: " + _cbStruct + "; iMac: " + _iMac + ")"; return "PLCF (cbStruct: " + _cbStruct + "; iMac: " + _iMac + ")";
} }
} }

View File

@ -26,180 +26,161 @@ import org.apache.poi.util.POILogger;
/** /**
* Represents a lightweight node in the Trees used to store content * Represents a lightweight node in the Trees used to store content
* properties. * properties.
* This only ever works in characters. For the few odd cases when * This only ever works in characters. For the few odd cases when
* the start and end aren't in characters (eg PAPX and CHPX), use * the start and end aren't in characters (eg PAPX and CHPX), use
* {@link BytePropertyNode} between you and this. * {@link BytePropertyNode} between you and this.
* *
* @author Ryan Ackley * @author Ryan Ackley
*/ */
@Internal @Internal
public abstract class PropertyNode<T extends PropertyNode<T>> implements Comparable<T>, Cloneable public abstract class PropertyNode<T extends PropertyNode<T>> implements Comparable<T>, Cloneable {
{
public static final class EndComparator implements public static final class EndComparator implements
Comparator<PropertyNode<?>> Comparator<PropertyNode<?>> {
{
public static final EndComparator instance = new EndComparator(); public static final EndComparator instance = new EndComparator();
public int compare( PropertyNode<?> o1, PropertyNode<?> o2 ) public int compare(PropertyNode<?> o1, PropertyNode<?> o2) {
{
int thisVal = o1.getEnd(); int thisVal = o1.getEnd();
int anotherVal = o2.getEnd(); int anotherVal = o2.getEnd();
return ( thisVal < anotherVal ? -1 : ( thisVal == anotherVal ? 0 return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0
: 1 ) ); : 1));
} }
} }
public static final class StartComparator implements public static final class StartComparator implements
Comparator<PropertyNode<?>> Comparator<PropertyNode<?>> {
{
public static final StartComparator instance = new StartComparator(); public static final StartComparator instance = new StartComparator();
public int compare( PropertyNode<?> o1, PropertyNode<?> o2 ) public int compare(PropertyNode<?> o1, PropertyNode<?> o2) {
{
int thisVal = o1.getStart(); int thisVal = o1.getStart();
int anotherVal = o2.getStart(); int anotherVal = o2.getStart();
return ( thisVal < anotherVal ? -1 : ( thisVal == anotherVal ? 0 return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0
: 1 ) ); : 1));
} }
} }
private final static POILogger _logger = POILogFactory.getLogger(PropertyNode.class); private final static POILogger _logger = POILogFactory.getLogger(PropertyNode.class);
protected Object _buf; protected Object _buf;
/** The start, in characters */ /**
private int _cpStart; * The start, in characters
/** The end, in characters */ */
private int _cpEnd; private int _cpStart;
/**
* The end, in characters
*/
private int _cpEnd;
/** /**
* @param fcStart The start of the text for this property, in characters. * @param fcStart The start of the text for this property, in characters.
* @param fcEnd The end of the text for this property, in characters. * @param fcEnd The end of the text for this property, in characters.
* @param buf FIXME: Old documentation is: "grpprl The property description in compressed form." * @param buf FIXME: Old documentation is: "grpprl The property description in compressed form."
*/ */
protected PropertyNode(int fcStart, int fcEnd, Object buf) protected PropertyNode(int fcStart, int fcEnd, Object buf) {
{ _cpStart = fcStart;
_cpStart = fcStart; _cpEnd = fcEnd;
_cpEnd = fcEnd; _buf = buf;
_buf = buf;
if(_cpStart < 0) { if (_cpStart < 0) {
_logger.log(POILogger.WARN, "A property claimed to start before zero, at " + _cpStart + "! Resetting it to zero, and hoping for the best"); _logger.log(POILogger.WARN, "A property claimed to start before zero, at " + _cpStart + "! Resetting it to zero, and hoping for the best");
_cpStart = 0; _cpStart = 0;
} }
if ( _cpEnd < _cpStart ) if (_cpEnd < _cpStart) {
{ _logger.log(POILogger.WARN, "A property claimed to end (" + _cpEnd
_logger.log( POILogger.WARN, "A property claimed to end (" + _cpEnd
+ ") before start! " + ") before start! "
+ "Resetting end to start, and hoping for the best" ); + "Resetting end to start, and hoping for the best");
_cpEnd = _cpStart; _cpEnd = _cpStart;
} }
} }
/** /**
* @return The start offset of this property's text. * @return The start offset of this property's text.
*/ */
public int getStart() public int getStart() {
{ return _cpStart;
return _cpStart; }
}
public void setStart(int start) public void setStart(int start) {
{ _cpStart = start;
_cpStart = start; }
}
/** /**
* @return The offset of the end of this property's text. * @return The offset of the end of this property's text.
*/ */
public int getEnd() public int getEnd() {
{ return _cpEnd;
return _cpEnd; }
}
public void setEnd(int end) public void setEnd(int end) {
{ _cpEnd = end;
_cpEnd = end; }
}
/** /**
* Adjust for a deletion that can span multiple PropertyNodes. * Adjust for a deletion that can span multiple PropertyNodes.
* @param start *
* @param length * @param start
*/ * @param length
public void adjustForDelete(int start, int length) */
{ public void adjustForDelete(int start, int length) {
int end = start + length; int end = start + length;
if (_cpEnd > start) { if (_cpEnd > start) {
// The start of the change is before we end // The start of the change is before we end
if (_cpStart < end) { if (_cpStart < end) {
// The delete was somewhere in the middle of us // The delete was somewhere in the middle of us
_cpEnd = end >= _cpEnd ? start : _cpEnd - length; _cpEnd = end >= _cpEnd ? start : _cpEnd - length;
_cpStart = Math.min(start, _cpStart); _cpStart = Math.min(start, _cpStart);
} else { } else {
// The delete was before us // The delete was before us
_cpEnd -= length; _cpEnd -= length;
_cpStart -= length; _cpStart -= length;
}
} }
} }
}
protected boolean limitsAreEqual(Object o) protected boolean limitsAreEqual(Object o) {
{ return ((PropertyNode<?>) o).getStart() == _cpStart &&
return ((PropertyNode<?>)o).getStart() == _cpStart && ((PropertyNode<?>) o).getEnd() == _cpEnd;
((PropertyNode<?>)o).getEnd() == _cpEnd;
} }
@Override @Override
public int hashCode() public int hashCode() {
{
return this._cpStart * 31 + this._buf.hashCode(); return this._cpStart * 31 + this._buf.hashCode();
} }
public boolean equals(Object o) public boolean equals(Object o) {
{ if (!(o instanceof PropertyNode)) return false;
if (!(o instanceof PropertyNode)) return false;
if (limitsAreEqual(o)) if (limitsAreEqual(o)) {
{ Object testBuf = ((PropertyNode<?>) o)._buf;
Object testBuf = ((PropertyNode<?>)o)._buf; if (testBuf instanceof byte[] && _buf instanceof byte[]) {
if (testBuf instanceof byte[] && _buf instanceof byte[]) return Arrays.equals((byte[]) testBuf, (byte[]) _buf);
{ }
return Arrays.equals((byte[])testBuf, (byte[])_buf); return _buf.equals(testBuf);
} }
return _buf.equals(testBuf); return false;
} }
return false;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public T clone() throws CloneNotSupportedException public T clone() throws CloneNotSupportedException {
{ return (T) super.clone();
return (T) super.clone(); }
}
/** /**
* Used for sorting in collections. * Used for sorting in collections.
*/ */
public int compareTo(T o) public int compareTo(T o) {
{ int cpEnd = o.getEnd();
int cpEnd = o.getEnd(); if (_cpEnd == cpEnd) {
if(_cpEnd == cpEnd) return 0;
{ } else if (_cpEnd < cpEnd) {
return 0; return -1;
} } else {
else if(_cpEnd < cpEnd) return 1;
{ }
return -1; }
}
else
{
return 1;
}
}
} }

View File

@ -25,203 +25,185 @@ import org.apache.poi.util.Internal;
/** /**
* Lightweight representation of a text piece. * Lightweight representation of a text piece.
* Works in the character domain, not the byte domain, so you * Works in the character domain, not the byte domain, so you
* need to have turned byte references into character * need to have turned byte references into character
* references before getting here. * references before getting here.
* *
* @author Ryan Ackley * @author Ryan Ackley
*/ */
@Internal @Internal
public class TextPiece extends PropertyNode<TextPiece> public class TextPiece extends PropertyNode<TextPiece> {
{ private boolean _usesUnicode;
private boolean _usesUnicode;
private PieceDescriptor _pd; private PieceDescriptor _pd;
/** /**
* @param start * @param start Beginning offset in main document stream, in characters.
* Beginning offset in main document stream, in characters. * @param end Ending offset in main document stream, in characters.
* @param end * @param text The raw bytes of our text
* Ending offset in main document stream, in characters. * @deprecated Use {@link #TextPiece(int, int, byte[], PieceDescriptor)}
* @param text * instead
* The raw bytes of our text
* @deprecated Use {@link #TextPiece(int,int,byte[],PieceDescriptor)}
* instead
*/ */
public TextPiece( int start, int end, byte[] text, PieceDescriptor pd, public TextPiece(int start, int end, byte[] text, PieceDescriptor pd,
int cpStart ) int cpStart) {
{ this(start, end, text, pd);
this( start, end, text, pd );
} }
/** /**
* @param start * @param start Beginning offset in main document stream, in characters.
* Beginning offset in main document stream, in characters. * @param end Ending offset in main document stream, in characters.
* @param end * @param text The raw bytes of our text
* Ending offset in main document stream, in characters.
* @param text
* The raw bytes of our text
*/ */
public TextPiece( int start, int end, byte[] text, PieceDescriptor pd ) public TextPiece(int start, int end, byte[] text, PieceDescriptor pd) {
{ super(start, end, buildInitSB(text, pd));
super(start, end, buildInitSB(text, pd)); _usesUnicode = pd.isUnicode();
_usesUnicode = pd.isUnicode(); _pd = pd;
_pd = pd;
// Validate // Validate
int textLength = ((CharSequence)_buf).length(); int textLength = ((CharSequence) _buf).length();
if(end-start != textLength) { if (end - start != textLength) {
throw new IllegalStateException("Told we're for characters " + start + " -> " + end + ", but actually covers " + textLength + " characters!"); throw new IllegalStateException("Told we're for characters " + start + " -> " + end + ", but actually covers " + textLength + " characters!");
} }
if(end < start) { if (end < start) {
throw new IllegalStateException("Told we're of negative size! start="+start + " end="+end); throw new IllegalStateException("Told we're of negative size! start=" + start + " end=" + end);
} }
} }
/** /**
* Create the StringBuilder from the text and unicode flag * Create the StringBuilder from the text and unicode flag
*/ */
private static StringBuilder buildInitSB(byte[] text, PieceDescriptor pd) { private static StringBuilder buildInitSB(byte[] text, PieceDescriptor pd) {
String str = new String(text, Charset.forName(pd.isUnicode() ? "UTF-16LE" : "Cp1252")); String str = new String(text, Charset.forName(pd.isUnicode() ? "UTF-16LE" : "Cp1252"));
return new StringBuilder(str); return new StringBuilder(str);
} }
/** /**
* @return If this text piece is unicode * @return If this text piece is unicode
*/ */
public boolean isUnicode() public boolean isUnicode() {
{ return _usesUnicode;
return _usesUnicode; }
}
public PieceDescriptor getPieceDescriptor() public PieceDescriptor getPieceDescriptor() {
{ return _pd;
return _pd; }
}
@Deprecated @Deprecated
public StringBuffer getStringBuffer() public StringBuffer getStringBuffer() {
{ return new StringBuffer(getStringBuilder());
return new StringBuffer(getStringBuilder()); }
}
public StringBuilder getStringBuilder() public StringBuilder getStringBuilder() {
{ return (StringBuilder) _buf;
return (StringBuilder)_buf; }
}
public byte[] getRawBytes() public byte[] getRawBytes() {
{ return ((CharSequence) _buf).toString().getBytes(
return ((CharSequence)_buf).toString().getBytes( Charset.forName(_usesUnicode ? "UTF-16LE" : "Cp1252")
Charset.forName(_usesUnicode ? "UTF-16LE" : "Cp1252") );
); }
}
/** /**
* Returns part of the string. * Returns part of the string.
* Works only in characters, not in bytes! * Works only in characters, not in bytes!
* @param start Local start position, in characters *
* @param end Local end position, in characters * @param start Local start position, in characters
*/ * @param end Local end position, in characters
@Deprecated */
public String substring(int start, int end) @Deprecated
{ public String substring(int start, int end) {
StringBuilder buf = (StringBuilder)_buf; StringBuilder buf = (StringBuilder) _buf;
// Validate // Validate
if(start < 0) { if (start < 0) {
throw new StringIndexOutOfBoundsException("Can't request a substring before 0 - asked for " + start); throw new StringIndexOutOfBoundsException("Can't request a substring before 0 - asked for " + start);
} }
if(end > buf.length()) { if (end > buf.length()) {
throw new StringIndexOutOfBoundsException("Index " + end + " out of range 0 -> " + buf.length()); throw new StringIndexOutOfBoundsException("Index " + end + " out of range 0 -> " + buf.length());
} }
if(end < start) { if (end < start) {
throw new StringIndexOutOfBoundsException("Asked for text from " + start + " to " + end + ", which has an end before the start!"); throw new StringIndexOutOfBoundsException("Asked for text from " + start + " to " + end + ", which has an end before the start!");
} }
return buf.substring(start, end); return buf.substring(start, end);
} }
/** /**
* Adjusts the internal string for deletinging * Adjusts the internal string for deletinging
* some characters within this. * some characters within this.
* @param start The start position for the delete, in characters *
* @param length The number of characters to delete * @param start The start position for the delete, in characters
*/ * @param length The number of characters to delete
@Deprecated */
public void adjustForDelete(int start, int length) { @Deprecated
int numChars = length; public void adjustForDelete(int start, int length) {
int myStart = getStart();
int myStart = getStart(); int myEnd = getEnd();
int myEnd = getEnd(); int end = start + length;
int end = start + numChars;
/* do we have to delete from this text piece? */ /* do we have to delete from this text piece? */
if (start <= myEnd && end >= myStart) { if (start <= myEnd && end >= myStart) {
/* find where the deleted area overlaps with this text piece */ /* find where the deleted area overlaps with this text piece */
int overlapStart = Math.max(myStart, start); int overlapStart = Math.max(myStart, start);
int overlapEnd = Math.min(myEnd, end); int overlapEnd = Math.min(myEnd, end);
int bufStart = overlapStart - myStart; int bufStart = overlapStart - myStart;
int bufEnd = overlapEnd - myStart; int bufEnd = overlapEnd - myStart;
((StringBuilder)_buf).delete(bufStart, bufEnd); ((StringBuilder) _buf).delete(bufStart, bufEnd);
} }
// We need to invoke this even if text from this piece is not being // We need to invoke this even if text from this piece is not being
// deleted because the adjustment must propagate to all subsequent // deleted because the adjustment must propagate to all subsequent
// text pieces i.e., if text from tp[n] is being deleted, then // text pieces i.e., if text from tp[n] is being deleted, then
// tp[n + 1], tp[n + 2], etc. will need to be adjusted. // tp[n + 1], tp[n + 2], etc. will need to be adjusted.
// The superclass is expected to use a separate sentry for this. // The superclass is expected to use a separate sentry for this.
super.adjustForDelete(start, length); super.adjustForDelete(start, length);
} }
/** /**
* Returns the length, in characters * Returns the length, in characters
*/ */
@Deprecated @Deprecated
public int characterLength() public int characterLength() {
{ return (getEnd() - getStart());
return (getEnd() - getStart()); }
}
/**
* Returns the length, in bytes
*/
public int bytesLength() {
return (getEnd() - getStart()) * (_usesUnicode ? 2 : 1);
}
@Override /**
public boolean equals(Object o) * Returns the length, in bytes
{ */
if (!(o instanceof TextPiece)) return false; public int bytesLength() {
TextPiece tp = (TextPiece)o; return (getEnd() - getStart()) * (_usesUnicode ? 2 : 1);
assert(_buf != null && tp._buf != null && _pd != null && tp._pd != null); }
return (
limitsAreEqual(o)
&& tp._usesUnicode == this._usesUnicode
&& tp._buf.toString().equals(this._buf.toString())
&& tp._pd.equals(this._pd)
);
}
@Override @Override
public int hashCode() { public boolean equals(Object o) {
assert false : "hashCode not designed"; if (!(o instanceof TextPiece)) return false;
return 42; // any arbitrary constant will do TextPiece tp = (TextPiece) o;
} assert (_buf != null && tp._buf != null && _pd != null && tp._pd != null);
return (
limitsAreEqual(o)
&& tp._usesUnicode == this._usesUnicode
&& tp._buf.toString().equals(this._buf.toString())
&& tp._pd.equals(this._pd)
);
}
@Override
public int hashCode() {
assert false : "hashCode not designed";
return 42; // any arbitrary constant will do
}
/** /**
* Returns the character position we start at. * Returns the character position we start at.
*/ */
public int getCP() public int getCP() {
{ return getStart();
return getStart(); }
}
public String toString() public String toString() {
{
return "TextPiece from " + getStart() + " to " + getEnd() + " (" return "TextPiece from " + getStart() + " to " + getEnd() + " ("
+ getPieceDescriptor() + ")"; + getPieceDescriptor() + ")";
} }

View File

@ -22,36 +22,30 @@ import java.io.ByteArrayOutputStream;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
@Internal @Internal
public final class HWPFOutputStream extends ByteArrayOutputStream public final class HWPFOutputStream extends ByteArrayOutputStream {
{
int _offset; int _offset;
public HWPFOutputStream() public HWPFOutputStream() {
{ super();
super(); }
}
public int getOffset() public int getOffset() {
{ return _offset;
return _offset; }
}
public synchronized void reset() public synchronized void reset() {
{ super.reset();
super.reset(); _offset = 0;
_offset = 0; }
}
public synchronized void write(byte[] buf, int off, int len) public synchronized void write(byte[] buf, int off, int len) {
{ super.write(buf, off, len);
super.write(buf, off, len); _offset += len;
_offset += len; }
}
public synchronized void write(int b) public synchronized void write(int b) {
{ super.write(b);
super.write(b); _offset++;
_offset++; }
}
} }