public void TestGetDouble() { Assert.AreEqual(_DOUBLEs[0], LittleEndian.GetDouble(_DOUBLE_array), 0.000001); Assert.AreEqual(_DOUBLEs[1], LittleEndian.GetDouble(_DOUBLE_array, LittleEndianConstants.DOUBLE_SIZE), 0.000001); Assert.IsTrue(Double.IsNaN(LittleEndian.GetDouble(_nan_DOUBLE_array))); double nan = LittleEndian.GetDouble(_nan_DOUBLE_array); byte[] data = new byte[8]; LittleEndian.PutDouble(data, nan); for (int i = 0; i < data.Length; i++) { byte b = data[i]; Assert.AreEqual(data[i], _nan_DOUBLE_array[i]); } }
/// <summary> /// Reads a variant type from a byte array /// </summary> /// <param name="src">The byte array</param> /// <param name="offset">The offset in the byte array where the variant starts</param> /// <param name="Length">The Length of the variant including the variant type field</param> /// <param name="type">The variant type To Read</param> /// <param name="codepage">The codepage To use for non-wide strings</param> /// <returns>A Java object that corresponds best To the variant field. For /// example, a VT_I4 is returned as a {@link long}, a VT_LPSTR as a /// {@link String}.</returns> public static Object Read(byte[] src, int offset, int Length, long type, int codepage) { Object value; int o1 = offset; int l1 = Length - LittleEndianConsts.INT_SIZE; long lType = type; /* Instead of trying To Read 8-bit characters from a Unicode string, * Read 16-bit characters. */ if (codepage == (int)Constants.CP_UNICODE && type == Variant.VT_LPSTR) { lType = Variant.VT_LPWSTR; } switch ((int)lType) { case Variant.VT_EMPTY: { value = null; break; } case Variant.VT_I2: { /* * Read a short. In Java it is represented as an * Integer object. */ value = LittleEndian.GetShort(src, o1); break; } case Variant.VT_I4: { /* * Read a word. In Java it is represented as an * Integer object. */ value = LittleEndian.GetInt(src, o1); break; } case Variant.VT_I8: { /* * Read a double word. In Java it is represented as a * long object. */ value = LittleEndian.GetLong(src, o1); break; } case Variant.VT_R8: { /* * Read an eight-byte double value. In Java it is represented as * a Double object. */ value = LittleEndian.GetDouble(src, o1); break; } case Variant.VT_FILETIME: { /* * Read a FILETIME object. In Java it is represented * as a Date object. */ int low = LittleEndian.GetInt(src, o1); o1 += LittleEndianConsts.INT_SIZE; int high = LittleEndian.GetInt(src, o1); if (low == 0 && high == 0) { value = null; } else { value = Util.FiletimeToDate(high, low); } break; } case Variant.VT_LPSTR: { /* * Read a byte string. In Java it is represented as a * String object. The 0x00 bytes at the end must be * stripped. */ int first = o1 + LittleEndianConsts.INT_SIZE; long last = first + LittleEndian.GetUInt(src, o1) - 1; o1 += LittleEndianConsts.INT_SIZE; while (src[(int)last] == 0 && first <= last) { last--; } int l = (int)(last - first + 1); value = codepage != -1 ? Encoding.GetEncoding(codepage).GetString(src, first, l) : Encoding.UTF8.GetString(src, first, l); break; } case Variant.VT_LPWSTR: { /* * Read a Unicode string. In Java it is represented as * a String object. The 0x00 bytes at the end must be * stripped. */ int first = o1 + LittleEndianConsts.INT_SIZE; long last = first + LittleEndian.GetUInt(src, o1) - 1; long l = last - first; o1 += LittleEndianConsts.INT_SIZE; StringBuilder b = new StringBuilder((int)(last - first)); for (int i = 0; i <= l; i++) { int i1 = o1 + (i * 2); int i2 = i1 + 1; int high = src[i2] << 8; int low = src[i1] & 0x00ff; char c = (char)(high | low); b.Append(c); } /* Strip 0x00 characters from the end of the string: */ while (b.Length > 0 && b[b.Length - 1] == 0x00) { b.Length = b.Length - 1; } value = b.ToString(); break; } case Variant.VT_CF: { if (l1 < 0) { /** * YK: reading the ClipboardData packet (VT_CF) is not quite correct. * The size of the data is determined by the first four bytes of the packet * while the current implementation calculates it in the Section constructor. * Test files in Bugzilla 42726 and 45583 clearly show that this approach does not always work. * The workaround below attempts to gracefully handle such cases instead of throwing exceptions. * * August 20, 2009 */ l1 = LittleEndian.GetInt(src, o1); o1 += LittleEndian.INT_SIZE; } byte[] v = new byte[l1]; for (int i = 0; i < l1; i++) { v[i] = src[(o1 + i)]; } value = v; break; } case Variant.VT_BOOL: { /* * The first four bytes in src, from src[offset] To * src[offset + 3] contain the DWord for VT_BOOL, so * skip it, we don't need it. */ // int first = offset + LittleEndianConstants.INT_SIZE; long boolean = LittleEndian.GetUInt(src, o1); if (boolean != 0) { value = true; } else { value = false; } break; } default: { byte[] v = new byte[l1]; for (int i = 0; i < l1; i++) { v[i] = src[(o1 + i)]; } throw new ReadingNotSupportedException(type, v); } } return(value); }
public 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 = LittleEndian.GetShort(data, offset); return(4); case Variant.VT_I4: _value = LittleEndian.GetInt(data, offset); return(4); case Variant.VT_R4: _value = LittleEndian.GetShort(data, offset); return(4); case Variant.VT_R8: _value = 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).Size); case Variant.VT_ERROR: _value = 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 = data[offset]; return(1); case Variant.VT_UI1: _value = LittleEndian.GetUByte(data, offset); return(2); case Variant.VT_UI2: _value = LittleEndian.GetUShort(data, offset); return(4); case Variant.VT_UI4: _value = LittleEndian.GetUInt(data, offset); return(4); case Variant.VT_I8: _value = LittleEndian.GetLong(data, offset); return(8); case Variant.VT_UI8: _value = LittleEndian.GetByteArray(data, offset, 8); return(8); case Variant.VT_INT: _value = LittleEndian.GetInt(data, offset); return(4); case Variant.VT_UINT: _value = LittleEndian.GetUInt(data, offset); return(4); case Variant.VT_LPSTR: _value = new CodePageString(data, offset); return(((CodePageString)_value).Size); case Variant.VT_LPWSTR: _value = new UnicodeString(data, offset); return(((UnicodeString)_value).Size); case Variant.VT_FILETIME: _value = new Filetime(data, offset); return(Filetime.SIZE); case Variant.VT_BLOB: _value = new Blob(data, offset); return(((Blob)_value).Size); 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).Size); case Variant.VT_BLOB_OBJECT: _value = new Blob(data, offset); return(((Blob)_value).Size); case Variant.VT_CF: _value = new ClipboardData(data, offset); return(((ClipboardData)_value).Size); 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).Size); 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 InvalidOperationException( "Unknown (possibly, incorrect) TypedPropertyValue type: " + _type); } }