git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1187595 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_8_BETA5
@@ -0,0 +1,121 @@ | |||
package org.apache.poi.hpsf; | |||
import org.apache.poi.util.Internal; | |||
import org.apache.poi.util.LittleEndian; | |||
@Internal | |||
class Array | |||
{ | |||
static class ArrayDimension | |||
{ | |||
static final int SIZE = 8; | |||
private int _indexOffset; | |||
private long _size; | |||
ArrayDimension( byte[] data, int offset ) | |||
{ | |||
_size = LittleEndian.getUInt( data, offset ); | |||
_indexOffset = LittleEndian.getInt( data, offset | |||
+ LittleEndian.INT_SIZE ); | |||
} | |||
} | |||
static class ArrayHeader | |||
{ | |||
private ArrayDimension[] _dimensions; | |||
private int _type; | |||
ArrayHeader( byte[] data, int startOffset ) | |||
{ | |||
int offset = startOffset; | |||
_type = LittleEndian.getInt( data, offset ); | |||
offset += LittleEndian.INT_SIZE; | |||
long numDimensionsUnsigned = LittleEndian.getUInt( data, offset ); | |||
offset += LittleEndian.INT_SIZE; | |||
if ( !( 1 <= numDimensionsUnsigned && numDimensionsUnsigned <= 31 ) ) | |||
throw new IllegalPropertySetDataException( | |||
"Array dimension number " + numDimensionsUnsigned | |||
+ " is not in [1; 31] range" ); | |||
int numDimensions = (int) numDimensionsUnsigned; | |||
_dimensions = new ArrayDimension[numDimensions]; | |||
for ( int i = 0; i < numDimensions; i++ ) | |||
{ | |||
_dimensions[i] = new ArrayDimension( data, offset ); | |||
offset += ArrayDimension.SIZE; | |||
} | |||
} | |||
long getNumberOfScalarValues() | |||
{ | |||
long result = 1; | |||
for ( ArrayDimension dimension : _dimensions ) | |||
result *= dimension._size; | |||
return result; | |||
} | |||
int getSize() | |||
{ | |||
return LittleEndian.INT_SIZE * 2 + _dimensions.length | |||
* ArrayDimension.SIZE; | |||
} | |||
int getType() | |||
{ | |||
return _type; | |||
} | |||
} | |||
private ArrayHeader _header; | |||
private TypedPropertyValue[] _values; | |||
Array() | |||
{ | |||
} | |||
Array( final byte[] data, final int offset ) | |||
{ | |||
read( data, offset ); | |||
} | |||
int read( final byte[] data, final int startOffset ) | |||
{ | |||
int offset = startOffset; | |||
_header = new ArrayHeader( data, offset ); | |||
offset += _header.getSize(); | |||
long numberOfScalarsLong = _header.getNumberOfScalarValues(); | |||
if ( numberOfScalarsLong > Integer.MAX_VALUE ) | |||
throw new UnsupportedOperationException( | |||
"Sorry, but POI can't store array of properties with size of " | |||
+ numberOfScalarsLong + " in memory" ); | |||
int numberOfScalars = (int) numberOfScalarsLong; | |||
_values = new TypedPropertyValue[numberOfScalars]; | |||
final int type = _header._type; | |||
if ( type == Variant.VT_VARIANT ) | |||
{ | |||
for ( int i = 0; i < numberOfScalars; i++ ) | |||
{ | |||
TypedPropertyValue typedPropertyValue = new TypedPropertyValue(); | |||
offset += typedPropertyValue.read( data, offset ); | |||
} | |||
} | |||
else | |||
{ | |||
for ( int i = 0; i < numberOfScalars; i++ ) | |||
{ | |||
TypedPropertyValue typedPropertyValue = new TypedPropertyValue( | |||
type, null ); | |||
offset += typedPropertyValue.readValuePadded( data, offset ); | |||
} | |||
} | |||
return offset - startOffset; | |||
} | |||
} |
@@ -0,0 +1,30 @@ | |||
package org.apache.poi.hpsf; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.Internal; | |||
@Internal | |||
class Blob | |||
{ | |||
private byte[] _value; | |||
Blob( byte[] data, int offset ) | |||
{ | |||
int size = LittleEndian.getInt( data, offset ); | |||
if ( size == 0 ) | |||
{ | |||
_value = new byte[0]; | |||
return; | |||
} | |||
_value = LittleEndian.getByteArray( _value, offset | |||
+ LittleEndian.INT_SIZE, size ); | |||
} | |||
int getSize() | |||
{ | |||
return LittleEndian.INT_SIZE + _value.length; | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
package org.apache.poi.hpsf; | |||
import org.apache.poi.util.LittleEndian; | |||
class ClipboardData | |||
{ | |||
private int _format; | |||
private byte[] _value; | |||
ClipboardData( byte[] data, int offset ) | |||
{ | |||
int size = LittleEndian.getInt( data, offset ); | |||
if ( size < 4 ) | |||
throw new IllegalPropertySetDataException( | |||
"ClipboardData size less than 4 bytes " | |||
+ "(doesn't even have format field!)" ); | |||
_format = LittleEndian.getInt( data, offset + LittleEndian.INT_SIZE ); | |||
_value = LittleEndian.getByteArray( data, offset | |||
+ LittleEndian.INT_SIZE * 2, size - LittleEndian.INT_SIZE ); | |||
} | |||
int getSize() | |||
{ | |||
return LittleEndian.INT_SIZE * 2 + _value.length; | |||
} | |||
} |
@@ -0,0 +1,31 @@ | |||
package org.apache.poi.hpsf; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.Internal; | |||
@Internal | |||
class CodePageString | |||
{ | |||
byte[] _value; | |||
CodePageString( final byte[] data, final int startOffset ) | |||
{ | |||
int offset = startOffset; | |||
int size = LittleEndian.getInt( data, offset ); | |||
offset += LittleEndian.INT_SIZE; | |||
_value = LittleEndian.getByteArray( data, offset, size ); | |||
if ( _value[size - 1] != 0 ) | |||
throw new IllegalPropertySetDataException( | |||
"CodePageString started at offset #" + offset | |||
+ " is not NULL-terminated" ); | |||
} | |||
int getSize() | |||
{ | |||
return LittleEndian.INT_SIZE + _value.length; | |||
} | |||
} |
@@ -0,0 +1,18 @@ | |||
package org.apache.poi.hpsf; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.Internal; | |||
@Internal | |||
class Currency | |||
{ | |||
static final int SIZE = 8; | |||
private byte[] _value; | |||
Currency( byte[] data, int offset ) | |||
{ | |||
_value = LittleEndian.getByteArray( data, offset, SIZE ); | |||
} | |||
} |
@@ -0,0 +1,18 @@ | |||
package org.apache.poi.hpsf; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.Internal; | |||
@Internal | |||
class Date | |||
{ | |||
static final int SIZE = 8; | |||
private byte[] _value; | |||
Date( byte[] data, int offset ) | |||
{ | |||
_value = LittleEndian.getByteArray( data, offset, SIZE ); | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
package org.apache.poi.hpsf; | |||
import org.apache.poi.util.Internal; | |||
import org.apache.poi.util.LittleEndian; | |||
@Internal | |||
class Decimal | |||
{ | |||
static final int SIZE = 16; | |||
private short field_1_wReserved; | |||
private byte field_2_scale; | |||
private byte field_3_sign; | |||
private int field_4_hi32; | |||
private long field_5_lo64; | |||
Decimal( final byte[] data, final int startOffset ) | |||
{ | |||
int offset = startOffset; | |||
field_1_wReserved = LittleEndian.getShort( data, offset ); | |||
offset += LittleEndian.SHORT_SIZE; | |||
field_2_scale = data[offset]; | |||
offset += LittleEndian.BYTE_SIZE; | |||
field_3_sign = data[offset]; | |||
offset += LittleEndian.BYTE_SIZE; | |||
field_4_hi32 = LittleEndian.getInt( data, offset ); | |||
offset += LittleEndian.INT_SIZE; | |||
field_5_lo64 = LittleEndian.getLong( data, offset ); | |||
offset += LittleEndian.LONG_SIZE; | |||
} | |||
} |
@@ -0,0 +1,17 @@ | |||
package org.apache.poi.hpsf; | |||
import org.apache.poi.util.LittleEndian; | |||
class Filetime | |||
{ | |||
static final int SIZE = LittleEndian.LONG_SIZE * 2; | |||
private long _dwLowDateTime; | |||
private long _dwHighDateTime; | |||
Filetime( byte[] data, int offset ) | |||
{ | |||
_dwLowDateTime = LittleEndian.getLong( data, offset + 0 ); | |||
_dwHighDateTime = LittleEndian.getLong( data, offset + 4 ); | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
package org.apache.poi.hpsf; | |||
import org.apache.poi.util.Internal; | |||
import org.apache.poi.util.LittleEndian; | |||
@Internal | |||
class GUID | |||
{ | |||
static final int SIZE = 16; | |||
private int _data1; | |||
private short _data2; | |||
private short _data3; | |||
private long _data4; | |||
GUID( byte[] data, int offset ) | |||
{ | |||
_data1 = LittleEndian.getInt( data, offset + 0 ); | |||
_data2 = LittleEndian.getShort( data, offset + 4 ); | |||
_data3 = LittleEndian.getShort( data, offset + 6 ); | |||
_data4 = LittleEndian.getLong( data, offset + 8 ); | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
package org.apache.poi.hpsf; | |||
import org.apache.poi.util.Internal; | |||
@Internal | |||
class IndirectPropertyName | |||
{ | |||
private CodePageString _value; | |||
IndirectPropertyName( byte[] data, int offset ) | |||
{ | |||
_value = new CodePageString( data, offset ); | |||
} | |||
int getSize() | |||
{ | |||
return _value.getSize(); | |||
} | |||
} |
@@ -0,0 +1,224 @@ | |||
package org.apache.poi.hpsf; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.Internal; | |||
@Internal | |||
class TypedPropertyValue | |||
{ | |||
private int _type; | |||
private Object _value; | |||
TypedPropertyValue() | |||
{ | |||
} | |||
TypedPropertyValue( byte[] data, int startOffset ) | |||
{ | |||
read( data, startOffset ); | |||
} | |||
TypedPropertyValue( int type, Object value ) | |||
{ | |||
_type = type; | |||
_value = value; | |||
} | |||
int read( byte[] data, int startOffset ) | |||
{ | |||
int offset = startOffset; | |||
_type = LittleEndian.getShort( data, offset ); | |||
offset += LittleEndian.SHORT_SIZE; | |||
short padding = LittleEndian.getShort( data, offset ); | |||
if ( padding != 0 ) | |||
throw new IllegalPropertySetDataException( | |||
"Property padding at offset " + offset | |||
+ " MUST be 0, but it's value is " + padding ); | |||
offset += LittleEndian.SHORT_SIZE; | |||
offset += readValuePadded( data, offset ); | |||
return offset - startOffset; | |||
} | |||
int readValue( byte[] data, int offset ) | |||
{ | |||
switch ( _type ) | |||
{ | |||
case Variant.VT_EMPTY: | |||
case Variant.VT_NULL: | |||
_value = null; | |||
return 0; | |||
case Variant.VT_I2: | |||
_value = Short.valueOf( LittleEndian.getShort( data, offset ) ); | |||
return 4; | |||
case Variant.VT_I4: | |||
_value = Integer.valueOf( LittleEndian.getInt( data, offset ) ); | |||
return 4; | |||
case Variant.VT_R4: | |||
_value = Short.valueOf( LittleEndian.getShort( data, offset ) ); | |||
return 4; | |||
case Variant.VT_R8: | |||
_value = Double.valueOf( LittleEndian.getDouble( data, offset ) ); | |||
return 8; | |||
case Variant.VT_CY: | |||
_value = new Currency( data, offset ); | |||
return Currency.SIZE; | |||
case Variant.VT_DATE: | |||
_value = new Date( data, offset ); | |||
return Date.SIZE; | |||
case Variant.VT_BSTR: | |||
_value = new CodePageString( data, offset ); | |||
return ( (CodePageString) _value ).getSize(); | |||
case Variant.VT_ERROR: | |||
_value = Long.valueOf( LittleEndian.getUInt( data, offset ) ); | |||
return 4; | |||
case Variant.VT_BOOL: | |||
_value = new VariantBool( data, offset ); | |||
return VariantBool.SIZE; | |||
case Variant.VT_DECIMAL: | |||
_value = new Decimal( data, offset ); | |||
return Decimal.SIZE; | |||
case Variant.VT_I1: | |||
_value = Byte.valueOf( data[offset] ); | |||
return 1; | |||
case Variant.VT_UI1: | |||
_value = Short.valueOf( LittleEndian.getUByte( data, offset ) ); | |||
return 2; | |||
case Variant.VT_UI2: | |||
_value = Integer.valueOf( LittleEndian.getUShort( data, offset ) ); | |||
return 4; | |||
case Variant.VT_UI4: | |||
_value = Long.valueOf( LittleEndian.getUInt( data, offset ) ); | |||
return 4; | |||
case Variant.VT_I8: | |||
_value = Long.valueOf( LittleEndian.getLong( data, offset ) ); | |||
return 8; | |||
case Variant.VT_UI8: | |||
_value = LittleEndian.getByteArray( data, offset, 8 ); | |||
return 8; | |||
case Variant.VT_INT: | |||
_value = Integer.valueOf( LittleEndian.getInt( data, offset ) ); | |||
return 4; | |||
case Variant.VT_UINT: | |||
_value = Long.valueOf( LittleEndian.getUInt( data, offset ) ); | |||
return 4; | |||
case Variant.VT_LPSTR: | |||
_value = new CodePageString( data, offset ); | |||
return ( (CodePageString) _value ).getSize(); | |||
case Variant.VT_LPWSTR: | |||
_value = new UnicodeString( data, offset ); | |||
return ( (UnicodeString) _value ).getSize(); | |||
case Variant.VT_FILETIME: | |||
_value = new Filetime( data, offset ); | |||
return Filetime.SIZE; | |||
case Variant.VT_BLOB: | |||
_value = new Blob( data, offset ); | |||
return ( (Blob) _value ).getSize(); | |||
case Variant.VT_STREAM: | |||
case Variant.VT_STORAGE: | |||
case Variant.VT_STREAMED_OBJECT: | |||
case Variant.VT_STORED_OBJECT: | |||
_value = new IndirectPropertyName( data, offset ); | |||
return ( (IndirectPropertyName) _value ).getSize(); | |||
case Variant.VT_BLOB_OBJECT: | |||
_value = new Blob( data, offset ); | |||
return ( (Blob) _value ).getSize(); | |||
case Variant.VT_CF: | |||
_value = new ClipboardData( data, offset ); | |||
return ( (ClipboardData) _value ).getSize(); | |||
case Variant.VT_CLSID: | |||
_value = new GUID( data, offset ); | |||
return GUID.SIZE; | |||
case Variant.VT_VERSIONED_STREAM: | |||
_value = new VersionedStream( data, offset ); | |||
return ( (VersionedStream) _value ).getSize(); | |||
case Variant.VT_VECTOR | Variant.VT_I2: | |||
case Variant.VT_VECTOR | Variant.VT_I4: | |||
case Variant.VT_VECTOR | Variant.VT_R4: | |||
case Variant.VT_VECTOR | Variant.VT_R8: | |||
case Variant.VT_VECTOR | Variant.VT_CY: | |||
case Variant.VT_VECTOR | Variant.VT_DATE: | |||
case Variant.VT_VECTOR | Variant.VT_BSTR: | |||
case Variant.VT_VECTOR | Variant.VT_ERROR: | |||
case Variant.VT_VECTOR | Variant.VT_BOOL: | |||
case Variant.VT_VECTOR | Variant.VT_VARIANT: | |||
case Variant.VT_VECTOR | Variant.VT_I1: | |||
case Variant.VT_VECTOR | Variant.VT_UI1: | |||
case Variant.VT_VECTOR | Variant.VT_UI2: | |||
case Variant.VT_VECTOR | Variant.VT_UI4: | |||
case Variant.VT_VECTOR | Variant.VT_I8: | |||
case Variant.VT_VECTOR | Variant.VT_UI8: | |||
case Variant.VT_VECTOR | Variant.VT_LPSTR: | |||
case Variant.VT_VECTOR | Variant.VT_LPWSTR: | |||
case Variant.VT_VECTOR | Variant.VT_FILETIME: | |||
case Variant.VT_VECTOR | Variant.VT_CF: | |||
case Variant.VT_VECTOR | Variant.VT_CLSID: | |||
_value = new Vector( (short) ( _type & 0x0FFF ) ); | |||
return ( (Vector) _value ).read( data, offset ); | |||
case Variant.VT_ARRAY | Variant.VT_I2: | |||
case Variant.VT_ARRAY | Variant.VT_I4: | |||
case Variant.VT_ARRAY | Variant.VT_R4: | |||
case Variant.VT_ARRAY | Variant.VT_R8: | |||
case Variant.VT_ARRAY | Variant.VT_CY: | |||
case Variant.VT_ARRAY | Variant.VT_DATE: | |||
case Variant.VT_ARRAY | Variant.VT_BSTR: | |||
case Variant.VT_ARRAY | Variant.VT_ERROR: | |||
case Variant.VT_ARRAY | Variant.VT_BOOL: | |||
case Variant.VT_ARRAY | Variant.VT_VARIANT: | |||
case Variant.VT_ARRAY | Variant.VT_DECIMAL: | |||
case Variant.VT_ARRAY | Variant.VT_I1: | |||
case Variant.VT_ARRAY | Variant.VT_UI1: | |||
case Variant.VT_ARRAY | Variant.VT_UI2: | |||
case Variant.VT_ARRAY | Variant.VT_UI4: | |||
case Variant.VT_ARRAY | Variant.VT_INT: | |||
case Variant.VT_ARRAY | Variant.VT_UINT: | |||
_value = new Array(); | |||
return ( (Array) _value ).read( data, offset ); | |||
default: | |||
throw new UnsupportedOperationException( | |||
"Unknown (possibly, incorrect) TypedPropertyValue type: " | |||
+ _type ); | |||
} | |||
} | |||
int readValuePadded( byte[] data, int offset ) | |||
{ | |||
int nonPadded = readValue( data, offset ); | |||
return ( nonPadded & 0x03 ) == 0 ? nonPadded : nonPadded | |||
+ ( 4 - ( nonPadded & 0x03 ) ); | |||
} | |||
} |
@@ -0,0 +1,35 @@ | |||
package org.apache.poi.hpsf; | |||
import org.apache.poi.util.Internal; | |||
import org.apache.poi.util.LittleEndian; | |||
@Internal | |||
class UnicodeString | |||
{ | |||
private byte[] _value; | |||
UnicodeString( byte[] data, int offset ) | |||
{ | |||
int length = LittleEndian.getInt( data, offset ); | |||
if ( length == 0 ) | |||
{ | |||
_value = new byte[0]; | |||
return; | |||
} | |||
_value = new byte[length * 2]; | |||
LittleEndian.getByteArray( data, offset + LittleEndian.INT_SIZE, | |||
length * 2 ); | |||
if ( _value[length * 2 - 1] != 0 || _value[length * 2 - 2] != 0 ) | |||
throw new IllegalPropertySetDataException( | |||
"UnicodeString started at offset #" + offset | |||
+ " is not NULL-terminated" ); | |||
} | |||
int getSize() | |||
{ | |||
return LittleEndian.INT_SIZE + _value.length; | |||
} | |||
} |
@@ -298,6 +298,14 @@ public class Variant | |||
*/ | |||
public static final int VT_CLSID = 72; | |||
/** | |||
* "MUST be a VersionedStream. The storage representing the (non-simple) | |||
* property set MUST have a stream element with the name in the StreamName | |||
* field." -- [MS-OLEPS] -- v20110920; Object Linking and Embedding (OLE) | |||
* Property Set Data Structures; page 24 / 63 | |||
*/ | |||
public static final int VT_VERSIONED_STREAM = 0x0049; | |||
/** | |||
* <p>[P] simple counted array. <span style="background-color: | |||
* #ffff00">How long is this? How is it to be |
@@ -0,0 +1,32 @@ | |||
package org.apache.poi.hpsf; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.Internal; | |||
@Internal | |||
class VariantBool | |||
{ | |||
static final int SIZE = 2; | |||
private boolean _value; | |||
VariantBool( byte[] data, int offset ) | |||
{ | |||
short value = LittleEndian.getShort( data, offset ); | |||
if ( value == 0x0000 ) | |||
{ | |||
_value = false; | |||
return; | |||
} | |||
if ( value == 0xffff ) | |||
{ | |||
_value = true; | |||
return; | |||
} | |||
throw new IllegalPropertySetDataException( "VARIANT_BOOL value '" | |||
+ value + "' is incorrect" ); | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
package org.apache.poi.hpsf; | |||
import java.io.UnsupportedEncodingException; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import org.apache.poi.util.LittleEndian; | |||
/** | |||
* Holder for vector-type properties | |||
* | |||
* @author Sergey Vladimirov (vlsergey {at} gmail {dot} com) | |||
*/ | |||
public class VariantVector | |||
{ | |||
private final List<Property> values; | |||
public VariantVector( int codepage, long id, long type, byte[] data, int startOffset ) | |||
throws UnsupportedEncodingException, ReadingNotSupportedException | |||
{ | |||
if ( ( type & 0x1000 ) != 0x1000 ) | |||
throw new IllegalArgumentException( "Specified type is not vector" ); | |||
final long elementType = type ^ 0x1000; | |||
int offset = startOffset; | |||
final long longLength = LittleEndian.getUInt( data, offset ); | |||
offset += LittleEndian.INT_SIZE; | |||
if ( longLength > Integer.MAX_VALUE ) | |||
throw new UnsupportedOperationException( "Vector is too long -- " | |||
+ longLength ); | |||
final int length = (int) longLength; | |||
this.values = new ArrayList<Property>(); | |||
for ( int i = 0; i < length; i++ ) | |||
{ | |||
Property property = new Property( id, elementType, null ); | |||
VariantSupport.read( data, offset, length, elementType, codepage ); | |||
} | |||
} | |||
} |
@@ -0,0 +1,64 @@ | |||
package org.apache.poi.hpsf; | |||
import org.apache.poi.util.Internal; | |||
import org.apache.poi.util.LittleEndian; | |||
/** | |||
* Holder for vector-type properties | |||
* | |||
* @author Sergey Vladimirov (vlsergey {at} gmail {dot} com) | |||
*/ | |||
@Internal | |||
class Vector | |||
{ | |||
private final short _type; | |||
private TypedPropertyValue[] _values; | |||
Vector( short type ) | |||
{ | |||
this._type = type; | |||
} | |||
Vector( byte[] data, int startOffset, short type ) | |||
{ | |||
this._type = type; | |||
read( data, startOffset ); | |||
} | |||
int read( byte[] data, int startOffset ) | |||
{ | |||
int offset = startOffset; | |||
final long longLength = LittleEndian.getUInt( data, offset ); | |||
offset += LittleEndian.INT_SIZE; | |||
if ( longLength > Integer.MAX_VALUE ) | |||
throw new UnsupportedOperationException( "Vector is too long -- " | |||
+ longLength ); | |||
final int length = (int) longLength; | |||
_values = new TypedPropertyValue[length]; | |||
if ( _type == Variant.VT_VARIANT ) | |||
{ | |||
for ( int i = 0; i < length; i++ ) | |||
{ | |||
TypedPropertyValue value = new TypedPropertyValue(); | |||
offset += value.read( data, offset ); | |||
_values[i] = value; | |||
} | |||
} | |||
else | |||
{ | |||
for ( int i = 0; i < length; i++ ) | |||
{ | |||
TypedPropertyValue value = new TypedPropertyValue( _type, null ); | |||
offset += value.readValuePadded( data, offset ); | |||
_values[i] = value; | |||
} | |||
} | |||
return offset - startOffset; | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
package org.apache.poi.hpsf; | |||
import org.apache.poi.util.Internal; | |||
@Internal | |||
class VersionedStream | |||
{ | |||
private GUID _versionGuid; | |||
private IndirectPropertyName _streamName; | |||
VersionedStream( byte[] data, int offset ) | |||
{ | |||
_versionGuid = new GUID( data, offset ); | |||
_streamName = new IndirectPropertyName( data, offset + GUID.SIZE ); | |||
} | |||
int getSize() | |||
{ | |||
return GUID.SIZE + _streamName.getSize(); | |||
} | |||
} |