public Variant ReadVariant(string fieldName)
{
// read the encoding byte.
byte encodingByte = m_reader.ReadByte();
Variant value = new Variant();
if ((encodingByte & (byte)VariantArrayEncodingBits.Array) != 0)
{
// read the array length.
int length = m_reader.ReadInt32();
if (length < 0)
{
return value;
}
Array array = null;
BuiltInType builtInType = (BuiltInType)(encodingByte & (byte)VariantArrayEncodingBits.TypeMask);
switch (builtInType)
{
case BuiltInType.Boolean:
{
bool[] values = new bool[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadBoolean(null);
}
array = values;
break;
}
case BuiltInType.SByte:
{
sbyte[] values = new sbyte[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadSByte(null);
}
array = values;
break;
}
case BuiltInType.Byte:
{
byte[] values = new byte[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadByte(null);
}
array = values;
break;
}
case BuiltInType.Int16:
{
short[] values = new short[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadInt16(null);
}
array = values;
break;
}
case BuiltInType.UInt16:
{
ushort[] values = new ushort[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadUInt16(null);
}
array = values;
break;
}
case BuiltInType.Int32:
case BuiltInType.Enumeration:
{
int[] values = new int[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadInt32(null);
}
array = values;
break;
}
case BuiltInType.UInt32:
{
uint[] values = new uint[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadUInt32(null);
}
array = values;
break;
}
case BuiltInType.Int64:
{
long[] values = new long[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadInt64(null);
}
array = values;
break;
}
case BuiltInType.UInt64:
{
ulong[] values = new ulong[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadUInt64(null);
}
array = values;
break;
}
case BuiltInType.Float:
{
float[] values = new float[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadFloat(null);
}
array = values;
break;
}
case BuiltInType.Double:
{
double[] values = new double[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadDouble(null);
}
array = values;
break;
}
case BuiltInType.String:
{
string[] values = new string[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadString(null);
}
array = values;
break;
}
case BuiltInType.DateTime:
{
DateTime[] values = new DateTime[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadDateTime(null);
}
array = values;
break;
}
case BuiltInType.Guid:
{
Uuid[] values = new Uuid[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadGuid(null);
}
array = values;
break;
}
case BuiltInType.ByteString:
{
byte[][] values = new byte[length][];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadByteString(null);
}
array = values;
break;
}
case BuiltInType.XmlElement:
{
try
{
XmlElement[] values = new XmlElement[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadXmlElement(null);
}
array = values;
}
catch(Exception ex)
{
Utils.Trace(ex, "Error reading variant.");
}
break;
}
case BuiltInType.NodeId:
{
NodeId[] values = new NodeId[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadNodeId(null);
}
array = values;
break;
}
case BuiltInType.ExpandedNodeId:
{
ExpandedNodeId[] values = new ExpandedNodeId[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadExpandedNodeId(null);
}
array = values;
break;
}
case BuiltInType.StatusCode:
{
StatusCode[] values = new StatusCode[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadStatusCode(null);
}
array = values;
break;
}
case BuiltInType.QualifiedName:
{
QualifiedName[] values = new QualifiedName[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadQualifiedName(null);
}
array = values;
break;
}
case BuiltInType.LocalizedText:
{
LocalizedText[] values = new LocalizedText[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadLocalizedText(null);
}
array = values;
break;
}
case BuiltInType.ExtensionObject:
{
ExtensionObject[] values = new ExtensionObject[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadExtensionObject();
}
array = values;
break;
}
case BuiltInType.DataValue:
{
DataValue[] values = new DataValue[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadDataValue(null);
}
array = values;
break;
}
case BuiltInType.Variant:
{
Variant[] values = new Variant[length];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = ReadVariant(null);
}
array = values;
break;
}
default:
{
throw new ServiceResultException(
StatusCodes.BadDecodingError,
Utils.Format("Cannot decode unknown type in Variant object (0x{0:X2}).", encodingByte));
}
}
if (array == null)
{
value = new Variant(StatusCodes.BadEncodingError);
}
else
{
// check for multi-dimensional arrays.
if ((encodingByte & (byte)VariantArrayEncodingBits.ArrayDimensions) != 0)
{
Int32Collection dimensions = ReadInt32Array(null);
// check if ArrayDimensions are consistent with the ArrayLength.
if (dimensions == null || dimensions.Count == 0)
{
throw new ServiceResultException(
StatusCodes.BadDecodingError,
"ArrayDimensions not specified when ArrayDimensions encoding bit was set in Variant object.");
}
int[] dimensionsArray = dimensions.ToArray();
int matrixLength = 1;
for (int ii = 0; ii < dimensionsArray.Length; ii++)
{
if (dimensionsArray[ii] == 0 && length >0)
{
throw new ServiceResultException(
StatusCodes.BadDecodingError,
Utils.Format("ArrayDimensions [{0}] is zero in Variant object.", ii));
}
matrixLength *= dimensionsArray[ii];
}
if (matrixLength != length)
{
throw new ServiceResultException(StatusCodes.BadDecodingError, "ArrayDimensions does not match with the ArrayLength in Variant object.");
}
value = new Variant(new Matrix(array, builtInType, dimensions.ToArray()));
}
else
{
value = new Variant(array);
}
}
}
else
{
switch ((BuiltInType)encodingByte)
{
case BuiltInType.Null:
{
value.Value = null;
break;
}
case BuiltInType.Boolean:
{
value.Set(ReadBoolean(null));
break;
}
case BuiltInType.SByte:
{
value.Set(ReadSByte(null));
break;
}
case BuiltInType.Byte:
{
value.Set(ReadByte(null));
break;
}
case BuiltInType.Int16:
{
value.Set(ReadInt16(null));
break;
}
case BuiltInType.UInt16:
{
value.Set(ReadUInt16(null));
break;
}
case BuiltInType.Int32:
case BuiltInType.Enumeration:
{
value.Set(ReadInt32(null));
break;
}
case BuiltInType.UInt32:
{
value.Set(ReadUInt32(null));
break;
}
case BuiltInType.Int64:
{
value.Set(ReadInt64(null));
break;
}
case BuiltInType.UInt64:
{
value.Set(ReadUInt64(null));
break;
}
case BuiltInType.Float:
{
value.Set(ReadFloat(null));
break;
}
case BuiltInType.Double:
{
value.Set(ReadDouble(null));
break;
}
case BuiltInType.String:
{
value.Set(ReadString(null));
break;
}
case BuiltInType.DateTime:
{
value.Set(ReadDateTime(null));
break;
}
case BuiltInType.Guid:
{
value.Set(ReadGuid(null));
break;
}
case BuiltInType.ByteString:
{
value.Set(ReadByteString(null));
break;
}
case BuiltInType.XmlElement:
{
try
{
value.Set(ReadXmlElement(null));
}
catch(Exception ex)
{
Utils.Trace(ex, "Error reading xml element for variant.");
value.Set(StatusCodes.BadEncodingError);
}
break;
}
case BuiltInType.NodeId:
{
value.Set(ReadNodeId(null));
break;
}
case BuiltInType.ExpandedNodeId:
{
value.Set(ReadExpandedNodeId(null));
break;
}
case BuiltInType.StatusCode:
{
value.Set(ReadStatusCode(null));
break;
}
case BuiltInType.QualifiedName:
{
value.Set(ReadQualifiedName(null));
break;
}
case BuiltInType.LocalizedText:
{
value.Set(ReadLocalizedText(null));
break;
}
case BuiltInType.ExtensionObject:
{
value.Set(ReadExtensionObject());
break;
}
case BuiltInType.DataValue:
{
value.Set(ReadDataValue(null));
break;
}
default:
{
throw new ServiceResultException(
StatusCodes.BadDecodingError,
Utils.Format("Cannot decode unknown type in Variant object (0x{0:X2}).", encodingByte));
}
}
}
return value;
}