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
8654862616
commit
fddd46c4e6
121
src/java/org/apache/poi/hpsf/Array.java
Normal file
121
src/java/org/apache/poi/hpsf/Array.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
30
src/java/org/apache/poi/hpsf/Blob.java
Normal file
30
src/java/org/apache/poi/hpsf/Blob.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
27
src/java/org/apache/poi/hpsf/ClipboardData.java
Normal file
27
src/java/org/apache/poi/hpsf/ClipboardData.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
31
src/java/org/apache/poi/hpsf/CodePageString.java
Normal file
31
src/java/org/apache/poi/hpsf/CodePageString.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
18
src/java/org/apache/poi/hpsf/Currency.java
Normal file
18
src/java/org/apache/poi/hpsf/Currency.java
Normal file
@ -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 );
|
||||
}
|
||||
}
|
18
src/java/org/apache/poi/hpsf/Date.java
Normal file
18
src/java/org/apache/poi/hpsf/Date.java
Normal file
@ -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 );
|
||||
}
|
||||
}
|
37
src/java/org/apache/poi/hpsf/Decimal.java
Normal file
37
src/java/org/apache/poi/hpsf/Decimal.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
17
src/java/org/apache/poi/hpsf/Filetime.java
Normal file
17
src/java/org/apache/poi/hpsf/Filetime.java
Normal file
@ -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 );
|
||||
}
|
||||
}
|
24
src/java/org/apache/poi/hpsf/GUID.java
Normal file
24
src/java/org/apache/poi/hpsf/GUID.java
Normal file
@ -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 );
|
||||
}
|
||||
}
|
19
src/java/org/apache/poi/hpsf/IndirectPropertyName.java
Normal file
19
src/java/org/apache/poi/hpsf/IndirectPropertyName.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
224
src/java/org/apache/poi/hpsf/TypedPropertyValue.java
Normal file
224
src/java/org/apache/poi/hpsf/TypedPropertyValue.java
Normal file
@ -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 ) );
|
||||
}
|
||||
}
|
35
src/java/org/apache/poi/hpsf/UnicodeString.java
Normal file
35
src/java/org/apache/poi/hpsf/UnicodeString.java
Normal file
@ -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
|
||||
|
32
src/java/org/apache/poi/hpsf/VariantBool.java
Normal file
32
src/java/org/apache/poi/hpsf/VariantBool.java
Normal file
@ -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" );
|
||||
}
|
||||
}
|
43
src/java/org/apache/poi/hpsf/VariantVector.java
Normal file
43
src/java/org/apache/poi/hpsf/VariantVector.java
Normal file
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
64
src/java/org/apache/poi/hpsf/Vector.java
Normal file
64
src/java/org/apache/poi/hpsf/Vector.java
Normal file
@ -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;
|
||||
}
|
||||
|
||||
}
|
21
src/java/org/apache/poi/hpsf/VersionedStream.java
Normal file
21
src/java/org/apache/poi/hpsf/VersionedStream.java
Normal file
@ -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
Block a user