📄 variant.java
字号:
leos.writeDouble(var.date);
break;
// other simple types
case VarTypes.VT_BOOL:
leos.writeBoolean(var.boolVal);
break;
case VarTypes.VT_BSTR:
leos.writeStringUnicode(var.bstrVal);
break;
// dispatch references
case VarTypes.VT_DISPATCH:
leos.writeInt(DispatchPtr.IID_TOKEN);
leos.writeInt(var.pdispVal.getPeer());
leos.writeInt(var.pdispVal.getUnknown());
break;
case VarTypes.VT_UNKNOWN:
leos.writeInt(UnknownPtr.IID_TOKEN);
leos.writeInt(var.punkVal.getPeer());
leos.writeInt(var.punkVal.getUnknown());
break;
case VarTypes.VT_ERROR:
leos.writeInt(var.scode);
break;
case VarTypes.VT_NULL:
// do nothing
break;
default:
throw new COMException("Unable to serialize variant: " + var);
}
}
/**
* Marshall a Java-array onto the leos-output stream
* <br><br>
* The marshalling code is the "inverse" of the native code in the method
* deserializeVariantSafeArray() in Transform.cpp.
*/
private static void writeArray(Object array, int appendVt, LittleEndianOutputStream leos) throws COMException, IOException {
Class cls = array.getClass().getComponentType();
if (cls == Byte.TYPE) {
byte[] values = (byte[]) array;
leos.writeShort(VarTypes.VT_ARRAY | VarTypes.VT_UI1 | appendVt);
leos.writeInt(values.length);
for (int i = 0, n = values.length; i < n; i++) {
leos.writeByte(values[i]);
}
} else if (cls == Short.TYPE) {
short[] values = (short[]) array;
leos.writeShort(VarTypes.VT_ARRAY | VarTypes.VT_I2 | appendVt);
leos.writeInt(values.length);
for (int i = 0, n = values.length; i < n; i++) {
leos.writeShort(values[i]);
}
} else if (cls == Integer.TYPE) {
int[] values = (int[])array;
leos.writeShort(VarTypes.VT_ARRAY | VarTypes.VT_I4 | appendVt);
leos.writeInt(values.length);
for (int i = 0, n = values.length; i < n; i++) {
leos.writeInt(values[i]);
}
} else if (cls == Long.TYPE) {
long[] values = (long[])array;
leos.writeShort(VarTypes.VT_ARRAY | VarTypes.VT_I8 | appendVt);
leos.writeInt(values.length);
for (int i = 0, n = values.length; i < n; i++) {
leos.writeLong(values[i]);
}
} else if (cls == Float.TYPE) {
float[] values = (float[]) array;
leos.writeShort(VarTypes.VT_ARRAY | VarTypes.VT_R4 | appendVt);
leos.writeInt(values.length);
for (int i = 0, n = values.length; i < n; i++) {
leos.writeFloat(values[i]);
}
} else if (cls == Double.TYPE) {
double[] values = (double[]) array;
leos.writeShort(VarTypes.VT_ARRAY | VarTypes.VT_R8 | appendVt);
leos.writeInt(values.length);
for (int i = 0, n = values.length; i < n; i++) {
leos.writeDouble(values[i]);
}
} else if (Date.class.isAssignableFrom(cls)) {
Date[] values = (Date[]) array;
leos.writeShort(VarTypes.VT_ARRAY | VarTypes.VT_DATE | appendVt);
leos.writeInt(values.length);
for (int i = 0, n = values.length; i < n; i++) {
leos.writeDouble(DateUtil.getWin32Date(values[i]));
}
} else if (cls == Boolean.TYPE) {
boolean[] values = (boolean[]) array;
leos.writeShort(VarTypes.VT_ARRAY | VarTypes.VT_BOOL | appendVt);
leos.writeInt(values.length);
for (int i = 0, n = values.length; i < n; i++) {
leos.writeBoolean(values[i]);
}
} else if (cls == String.class) {
String[] values = (String[]) array;
leos.writeShort(VarTypes.VT_ARRAY | VarTypes.VT_BSTR | appendVt);
leos.writeInt(values.length);
for (int i = 0, n = values.length; i < n; i++) {
leos.writeStringUnicode(values[i]);
}
} else if (Object.class.isAssignableFrom(cls)) {
short subTypeVt = VarTypes.VT_VARIANT;
if (DispatchPtr.class.isAssignableFrom(cls)) {
subTypeVt = VarTypes.VT_DISPATCH;
} else if (UnknownPtr.class.isAssignableFrom(cls)) {
subTypeVt = VarTypes.VT_UNKNOWN;
}
Object[] values = (Object[]) array;
leos.writeShort(VarTypes.VT_ARRAY | subTypeVt | appendVt);
leos.writeInt(values.length);
for (int i = 0, n = values.length; i < n; i++) {
writeObject(values[i], leos);
}
} else {
throw new COMException("Type cannot be marshalled to variant-array: " + cls);
}
}
/**
* Unmarshall from the leis-input stream, into a Java-array.
* <br><br>
* The unmarshalling code is the "inverse" of the native code in the method
* serializeVariantSafeArray() in Transform.cpp.
*/
private static Object readArray(short vt, LittleEndianInputStream leis) throws COMException, IOException {
int length = leis.readInt();
switch (vt) {
case VarTypes.VT_I1:
case VarTypes.VT_UI1:
byte[] bytes = new byte[length];
for (int n = 0; n < length; n++) {
bytes[n] = leis.readByte();
}
return bytes;
case VarTypes.VT_I2:
case VarTypes.VT_UI2:
short[] shorts = new short[length];
for (int n = 0; n < length; n++) {
shorts[n] = leis.readShort();
}
return shorts;
case VarTypes.VT_I4:
case VarTypes.VT_UI4:
case VarTypes.VT_INT:
case VarTypes.VT_UINT:
case VarTypes.VT_ERROR:
int[] ints = new int[length];
for (int n = 0; n < length; n++) {
ints[n] = leis.readInt();
}
return ints;
case VarTypes.VT_I8:
case VarTypes.VT_UI8:
case VarTypes.VT_CY:
long[] longs = new long[length];
for (int n = 0; n < length; n++) {
longs[n] = leis.readLong();
}
return longs;
case VarTypes.VT_R4:
float[] floats = new float[length];
for (int n = 0; n < length; n++) {
floats[n] = leis.readFloat();
}
return floats;
case VarTypes.VT_R8:
double[] doubles = new double[length];
for (int n = 0; n < length; n++) {
doubles[n] = leis.readDouble();
}
return doubles;
case VarTypes.VT_DATE:
Date[] dates = new Date[length];
for (int n = 0; n < length; n++) {
dates[n] = new Date(DateUtil.getJavaDate(leis.readDouble()));
}
return dates;
case VarTypes.VT_BOOL:
boolean[] booleans = new boolean[length];
for (int n = 0; n < length; n++) {
booleans[n] = leis.readBoolean();
}
return booleans;
case VarTypes.VT_BSTR:
String[] strings = new String[length];
for (int n = 0; n < length; n++) {
strings[n] = leis.readStringUnicode();
}
return strings;
case VarTypes.VT_DISPATCH:
DispatchPtr[] dispatches = new DispatchPtr[length];
for (int n = 0; n < length; n++) {
dispatches[n] = (DispatchPtr)IdentityManager.getCOMPtr(leis, WellKnownGUIDs.IID_IDispatch);
}
return dispatches;
case VarTypes.VT_UNKNOWN:
UnknownPtr[] unknowns = new UnknownPtr[length];
for (int n = 0; n < length; n++) {
unknowns[n] = (UnknownPtr)IdentityManager.getCOMPtr(leis, WellKnownGUIDs.IID_IUnknown);
}
return unknowns;
case VarTypes.VT_VARIANT:
Object[] objects = new Object[length];
for (int n = 0; n < length; n++) {
objects[n] = readObject(leis);
}
return objects;
}
throw new COMException("Bad vartype in array: " + vt);
}
/**
* the method that does the actual work for {@link #readObject(LittleEndianInputStream)
*/
private static Object readObject(short vt, LittleEndianInputStream leis) throws COMException, IOException {
if (0 != (vt & VarTypes.VT_ARRAY)) {
return readArray((short) (vt & VarTypes.VT_TYPEMASK), leis);
}
if (0 != (vt & VarTypes.VT_BYREF)) {
return readObject((short) (vt & VarTypes.VT_TYPEMASK), leis);
}
int temp = 0;
switch (vt) {
case VarTypes.VT_EMPTY:
case VarTypes.VT_NULL:
return null;
case VarTypes.VT_I1:
case VarTypes.VT_UI1:
return new Byte(leis.readByte());
case VarTypes.VT_I2:
case VarTypes.VT_UI2:
return new Short(leis.readShort());
case VarTypes.VT_I4:
case VarTypes.VT_UI4:
case VarTypes.VT_INT:
case VarTypes.VT_UINT:
case VarTypes.VT_ERROR:
return new Integer(leis.readInt());
case VarTypes.VT_I8:
case VarTypes.VT_UI8:
case VarTypes.VT_CY:
return new Long(leis.readLong());
case VarTypes.VT_R4:
return new Float(leis.readFloat());
case VarTypes.VT_R8:
return new Double(leis.readDouble());
case VarTypes.VT_DATE:
return new Date(DateUtil.getJavaDate(leis.readDouble()));
case VarTypes.VT_BOOL:
return (leis.readBoolean() ? Boolean.TRUE: Boolean.FALSE);
case VarTypes.VT_BSTR:
return leis.readStringUnicode();
case VarTypes.VT_VARIANT:
return readObject(leis);
case VarTypes.VT_DISPATCH:
return IdentityManager.getCOMPtr(leis, WellKnownGUIDs.IID_IDispatch);
case VarTypes.VT_UNKNOWN:
return (IdentityManager.getCOMPtr(leis, WellKnownGUIDs.IID_IUnknown));
default:
throw new COMException("Unable to deserialize variant type: " + vt);
}
}
/**
* unmarshall an object from an input stream. The object will be unmarshalled
* following these rules:
* <ul>
* <li><b><code>VT_EMPTY</code> and <code>VT_NULL</code>:</b> will be unmarshalled as <code>null</code>.</li>
* <li><b><code>*|VT_BYREF</code>:</b> will be unmarshalled as the base <code>VT_TYPE</code>,
* ie. the returned object will NOT be wrapped in a {@link Variant.ByrefHolder}.</li>
* <li><b><code>*|VT_ARRAY</code>:</b> will be unmarshalled as an array of the base type.</li>
* <li><b><code>VT_I1</code> and <code>VT_UI1</code>:</b> will be unmarshalled as <code>Byte</code>.</li>
* <li><b><code>VT_I2</code> and <code>VT_UI2</code>:</b> will be unmarshalled as <code>Short</code>.</li>
* <li><b><code>VT_I4</code>, <code>VT_UI4</code>, <code>VT_INT</code>, <code>VT_UINT</code> and <code>VT_ERROR</code>:</b>
* will be unmarshalled as <code>Integer</code>.</li>
* <li><b><code>VT_I8</code>, <code>VT_UI8</code> and <code>VT_CY</code>:</b>
* will be unmarshalled as <code>Long</code>.</li>
* <li><b><code>VT_R4</code>:</b> will be unmarshalled as <code>Float</code>.</li>
* <li><b><code>VT_R8</code>:</b> will be unmarshalled as <code>Double</code>.</li>
* <li><b><code>VT_DATE</code>:</b> will be unmarshalled as <code>Date</code> using
* the {@link DateUtil#getJavaDate(double)}-method.</li>
* <li><b><code>VT_BOOL</code>:</b> will be unmarshalled as <code>Boolean</code>.</li>
* <li><b><code>VT_BSTR</code>:</b> will be unmarshalled as <code>String</code>.</li>
* <li><b><code>VT_VARIANT</code>:</b> will be unmarshalled as the wrapped base object,
* ie. will NOT be returned as a {@link Variant}-object.</li>
* <li><b><code>VT_DISPATCH</code>:</b> will be unmarshalled as a {@link DispatchPtr}-object.</li>
* <li><b><code>VT_UNKNOWN</code>:</b> will be unmarshalled as a {@link UnknownPtr}-object.</li>
* </ul>
* If none of the rules match, a COMException will be thrown.
* <br><br>
* <b>Arrays:</b> If the next object on the input stream is an object, this call
* will unmarshall the entire array. If it is an array of primitive types it will be
* returned as such (and NOT as an array of the wrapper class). Eg. if the next object
* on the stream is an int-array:
* <pre> int[] result = (int[])Variant.readObject(leis);</pre>
* <br><br>
* The unmarshalling code is the "inverse" of the native code in the method
* serializeVariant() in Transform.cpp
*
* @param leis the stream the object should be read from.
* @return the next object on the stream.
* @throws COMException if the object can not be unmarshalled due to an
* unknown <code>VT_TYPE</code> or due to IOExceptions on the stream.
*/
public static Object readObject(LittleEndianInputStream leis) throws COMException {
try {
short vt = leis.readShort();
return readObject(vt, leis);
} catch (IOException ioe) {
throw new COMException(ioe);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -