mirror of https://github.com/apache/poi.git
add classes that will replace VariantSupport class just a bit later
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1187595 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
aaadb09934
commit
0df5442322
|
@ -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;
|
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:
|
* <p>[P] simple counted array. <span style="background-color:
|
||||||
* #ffff00">How long is this? How is it to be
|
* #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();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue