專案

一般

配置概況

Bug #2903 » SECS.cs裡的.txt

莊 施嶔, 11/06/2025 10:23

 
public void SetValue(SecsIndexType type, object value, UInt32 lb = 0)
{
switch (type)
{
case SecsIndexType.U1:
case SecsIndexType.B: // Binary - often treated as a byte or byte array
case SecsIndexType.Boolean:
if (value is byte[] byteArray)
{
if (type == SecsIndexType.Boolean && byteArray.Length != 1)
{
throw new ArgumentException($"For Boolean type, byte array length must be 1, but got {byteArray.Length}. Value: {BitConverter.ToString(byteArray).Replace("-", "")}", nameof(value));
}
if (type == SecsIndexType.Boolean && !(byteArray[0] == 0 || byteArray[0] == 1))
{
throw new ArgumentOutOfRangeException(nameof(value), $"Boolean byte value '{byteArray[0]}' is not 0 or 1.");
}

if (type == SecsIndexType.U1) Set_U1(byteArray, lb);
else if (type == SecsIndexType.B) Set_B(byteArray, lb);
else if (type == SecsIndexType.Boolean) Set_Boolean(byteArray, lb);
}
else if (value is byte singleByte)
{
if (type == SecsIndexType.Boolean && !(singleByte == 0 || singleByte == 1))
{
throw new ArgumentOutOfRangeException(nameof(value), $"Boolean byte value '{singleByte}' is not 0 or 1.");
}
byte[] vbytes = new byte[1] { singleByte };
if (type == SecsIndexType.U1) Set_U1(vbytes, lb);
else if (type == SecsIndexType.B) Set_B(vbytes, lb);
else if (type == SecsIndexType.Boolean) Set_Boolean(vbytes, lb);
}
else
{
byte byteToSet = 0; // Initialize to prevent CS0165
bool conversionOk = false;

if (value is int i)
{
if (i >= 0 && i <= 255) { byteToSet = (byte)i; conversionOk = true; }
else { throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{i}' is out of byte range (0-255) for SECS type {type}."); }
}
else if (value is long l)
{
if (l >= 0 && l <= 255) { byteToSet = (byte)l; conversionOk = true; }
else { throw new ArgumentOutOfRangeException(nameof(value), $"Long value '{l}' is out of byte range (0-255) for SECS type {type}."); }
}
else if (value is uint ui)
{
if (ui <= 255) { byteToSet = (byte)ui; conversionOk = true; }
else { throw new ArgumentOutOfRangeException(nameof(value), $"UInt value '{ui}' is out of byte range (0-255) for SECS type {type}."); }
}
else if (value is string s)
{
// Consider NumberStyles and CultureInfo for robust parsing
if (byte.TryParse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out byteToSet)) { conversionOk = true; }
else { throw new ArgumentException($"String value '{s}' cannot be converted to byte for SECS type {type}.", nameof(value)); }
}
else if (type == SecsIndexType.Boolean && value is bool boolVal)
{
byteToSet = Convert.ToByte(boolVal);
conversionOk = true;
}

if (conversionOk)
{
if (type == SecsIndexType.Boolean && !(byteToSet == 0 || byteToSet == 1))
{
throw new ArgumentOutOfRangeException(nameof(value), $"Converted Boolean value '{byteToSet}' is not 0 or 1.");
}
byte[] vbytes = new byte[1] { byteToSet };
if (type == SecsIndexType.U1) Set_U1(vbytes, lb);
else if (type == SecsIndexType.B) Set_B(vbytes, lb);
else if (type == SecsIndexType.Boolean) Set_Boolean(vbytes, lb);
}
else
{
throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted to byte for SECS type {type}.", nameof(value));
}
}
break;

case SecsIndexType.U2:
if (value is ushort[] valUshortArray) { Set_U2(valUshortArray, lb); }
else if (value is short[] valShortArray) { Set_U2(Array.ConvertAll(valShortArray, Convert.ToUInt16), lb); }
else if (value is int[] valIntArrayForU2)
{
Set_U2(Array.ConvertAll(valIntArrayForU2, i => {
if (i < ushort.MinValue || i > ushort.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{i}' is out of UInt16 range for SECS type {type}.");
return Convert.ToUInt16(i);
}), lb);
}
else if (value is ushort valUshort) { Set_U2(new ushort[] { valUshort }, lb); }
else if (value is short valShort) { Set_U2(new ushort[] { Convert.ToUInt16(valShort) }, lb); } // Add range check if necessary
else if (value is int valIntForU2)
{
if (valIntForU2 < ushort.MinValue || valIntForU2 > ushort.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{valIntForU2}' is out of UInt16 range for SECS type {type}.");
Set_U2(new ushort[] { Convert.ToUInt16(valIntForU2) }, lb);
}
else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); }
break;
case SecsIndexType.U4:
if (value is uint[] valUintArray) { Set_U4(valUintArray, lb); }
else if (value is int[] valIntArrayForU4)
{
Set_U4(Array.ConvertAll(valIntArrayForU4, i => {
if (i < 0 && (long)i + uint.MaxValue + 1 != 0) { /* check for negative numbers that cannot be cast to uint without data loss, simple i < 0 is not enough for int.MinValue */ }
// A direct cast (uint)i for negative numbers will wrap around.
// Depending on desired behavior, either throw or convert carefully.
// For simplicity, let's assume positive or use Convert.ToUInt32 which throws for negatives.
return Convert.ToUInt32(i); // This will throw OverflowException for negative i
}), lb);
}
else if (value is uint valUint) { Set_U4(new uint[] { valUint }, lb); }
else if (value is int valIntForU4) { Set_U4(new uint[] { Convert.ToUInt32(valIntForU4) }, lb); } // Will throw for negative
else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); }
break;
case SecsIndexType.U8:
if (value is ulong[] valUlongArray) { Set_U8(valUlongArray, lb); }
else if (value is long[] valLongArrayForU8) { Set_U8(Array.ConvertAll(valLongArrayForU8, Convert.ToUInt64), lb); } // Throws for negative
else if (value is ulong valUlong) { Set_U8(new ulong[] { valUlong }, lb); }
else if (value is long valLongForU8) { Set_U8(new ulong[] { Convert.ToUInt64(valLongForU8) }, lb); } // Throws for negative
else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); }
break;

case SecsIndexType.I1:
if (value is sbyte[] valSbyteArray) { Set_I1(valSbyteArray, lb); }
else if (value is byte[] valByteArrayForI1) { Set_I1(Array.ConvertAll(valByteArrayForI1, Convert.ToSByte), lb); } // Throws if > 127
else if (value is int[] valIntArrayForI1)
{
Set_I1(Array.ConvertAll(valIntArrayForI1, i => {
if (i < SByte.MinValue || i > SByte.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{i}' is out of SByte range for SECS type {type}.");
return Convert.ToSByte(i);
}), lb);
}
else if (value is sbyte valSbyte) { Set_I1(new sbyte[] { valSbyte }, lb); }
else if (value is byte valByteForI1) { Set_I1(new sbyte[] { Convert.ToSByte(valByteForI1) }, lb); } // Throws if > 127
else if (value is int valIntForI1)
{
if (valIntForI1 < SByte.MinValue || valIntForI1 > SByte.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{valIntForI1}' is out of SByte range for SECS type {type}.");
Set_I1(new sbyte[] { Convert.ToSByte(valIntForI1) }, lb);
}
else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); }
break;
case SecsIndexType.I2:
if (value is short[] valShortArrayForI2) { Set_I2(valShortArrayForI2, lb); }
else if (value is int[] valIntArrayForI2)
{
Set_I2(Array.ConvertAll(valIntArrayForI2, i => {
if (i < short.MinValue || i > short.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{i}' is out of Int16 range for SECS type {type}.");
return Convert.ToInt16(i);
}), lb);
}
else if (value is short valShortForI2) { Set_I2(new short[] { valShortForI2 }, lb); }
else if (value is int valIntForI2)
{
if (valIntForI2 < short.MinValue || valIntForI2 > short.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{valIntForI2}' is out of Int16 range for SECS type {type}.");
Set_I2(new short[] { Convert.ToInt16(valIntForI2) }, lb);
}
else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); }
break;
case SecsIndexType.I4:
if (value is int[] valIntArrayForI4) { Set_I4(valIntArrayForI4, lb); }
else if (value is int valIntForI4) { Set_I4(new int[] { valIntForI4 }, lb); }
else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); }
break;
case SecsIndexType.I8:
if (value is long[] valLongArrayForI8) { Set_I8(valLongArrayForI8, lb); }
else if (value is long valLongForI8) { Set_I8(new long[] { valLongForI8 }, lb); }
else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); }
break;

case SecsIndexType.F4:
if (value is float[] valFloatArray) { Set_F4(valFloatArray, lb); }
else if (value is double[] valDblArrayForF4) { Set_F4(Array.ConvertAll(valDblArrayForF4, Convert.ToSingle), lb); }
else if (value is float valFloat) { Set_F4(new float[] { valFloat }, lb); }
else if (value is double valDblForF4) { Set_F4(new float[] { Convert.ToSingle(valDblForF4) }, lb); }
else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); }
break;
case SecsIndexType.F8:
if (value is double[] valDblArrayForF8) { Set_F8(valDblArrayForF8, lb); }
else if (value is float[] valFltArrayForF8) { Set_F8(Array.ConvertAll(valFltArrayForF8, f => (double)f), lb); }
else if (value is double valDblForF8) { Set_F8(new double[] { valDblForF8 }, lb); }
else if (value is float valFltForF8) { Set_F8(new double[] { (double)valFltForF8 }, lb); }
else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); }
break;

case SecsIndexType.List:
if (value is int listLength)
{
if (listLength < 0) throw new ArgumentOutOfRangeException(nameof(value), $"List length '{listLength}' cannot be negative for SECS type {type}.");
Set_List(listLength, lb);
}
else if (value is uint listLengthUint)
{ // Allow uint for length too
if (listLengthUint > int.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"List length '{listLengthUint}' is too large for SECS type {type}.");
Set_List((int)listLengthUint, lb);
}
else { throw new ArgumentException($"List length value '{value}' (type: {value?.GetType().FullName}) must be a non-negative integer for SECS type {type}.", nameof(value)); }
break;

case SecsIndexType.A:
case SecsIndexType.Ax:
case SecsIndexType.J:
case SecsIndexType.Jx:
string strValue = value?.ToString() ?? string.Empty; // 將 null 轉換為空字串
if (type == SecsIndexType.A) Set_A(strValue, lb);
else if (type == SecsIndexType.Ax) Set_Ax(strValue, lb);
else if (type == SecsIndexType.J) Set_J(strValue, lb);
else if (type == SecsIndexType.Jx) Set_Jx(strValue, lb);
break;

case SecsIndexType.A2: // Array of UInt16
if (value is ushort[] valUshortArrayForA2) { Set_A2(valUshortArrayForA2, lb); }
else if (value is int[] valIntArrayForA2)
{
Set_A2(Array.ConvertAll(valIntArrayForA2, i => {
if (i < ushort.MinValue || i > ushort.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{i}' is out of UInt16 range for SECS type {type}.");
return Convert.ToUInt16(i);
}), lb);
}
// Potentially convert string to ushort[] if A2 represents wide characters
else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); }
break;

default:
throw new NotSupportedException($"SECS type {type} is not currently supported in SetValue operation.");
}
}
(5-5/5)