Skip to content

Commit

Permalink
Backport more changes
Browse files Browse the repository at this point in the history
  • Loading branch information
slozier committed Dec 23, 2024
1 parent 2e347b5 commit 83689ee
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 77 deletions.
14 changes: 14 additions & 0 deletions Src/IronPython.Modules/_codecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,20 @@ public static PythonTuple mbcs_encode(CodeContext/*!*/ context, [NotNone] string

#endregion

#region OEM Functions

[SupportedOSPlatform("windows"), PythonHidden(PlatformsAttribute.PlatformFamily.Unix)]
public static PythonTuple oem_decode(CodeContext/*!*/ context, [NotNone] IBufferProtocol input, string? errors = null, bool final = false) {
using IPythonBuffer buffer = input.GetBuffer();
return DoDecode(context, "oem", StringOps.CodecsInfo.OemEncoding, buffer, errors).ToPythonTuple();
}

[SupportedOSPlatform("windows"), PythonHidden(PlatformsAttribute.PlatformFamily.Unix)]
public static PythonTuple oem_encode(CodeContext/*!*/ context, [NotNone] string input, string? errors = null)
=> DoEncode(context, "oem", StringOps.CodecsInfo.OemEncoding, input, errors).ToPythonTuple();

#endregion

#region Code Page Functions

[SupportedOSPlatform("windows"), PythonHidden(PlatformsAttribute.PlatformFamily.Unix)]
Expand Down
76 changes: 71 additions & 5 deletions Src/IronPython.Modules/_struct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,22 @@ public void __init__(CodeContext/*!*/ context, object fmt) {
break;
case FormatType.Float:
for (int j = 0; j < curFormat.Count; j++) {
WriteFloat(res, _isLittleEndian, (float)GetDoubleValue(context, curObj++, values));
var d = GetDoubleValue(context, curObj++, values);
var val = (float)d;
if (float.IsInfinity(val) && !double.IsInfinity(d)) throw PythonOps.OverflowError("float too large to pack with f format");
WriteFloat(res, _isLittleEndian, val);
}
break;
#if NET6_0_OR_GREATER
case FormatType.Half:
for (int j = 0; j < curFormat.Count; j++) {
var d = GetDoubleValue(context, curObj++, values);
var val = (Half)d;
if (Half.IsInfinity(val) && !double.IsInfinity(d)) throw PythonOps.OverflowError("float too large to pack with e format");
WriteHalf(res, _isLittleEndian, val);
}
break;
#endif
case FormatType.CString:
WriteString(res, curFormat.Count, GetStringValue(context, curObj++, values));
break;
Expand Down Expand Up @@ -273,7 +286,7 @@ public void pack_into(CodeContext/*!*/ context, [NotNone] IBufferProtocol/*!*/ b
break;
case FormatType.SignedChar:
for (int j = 0; j < curFormat.Count; j++) {
res[res_idx++] = (int)(sbyte)CreateCharValue(context, ref curIndex, data);
res[res_idx++] = (int)unchecked((sbyte)CreateCharValue(context, ref curIndex, data));
}
break;
case FormatType.UnsignedChar:
Expand Down Expand Up @@ -336,7 +349,7 @@ public void pack_into(CodeContext/*!*/ context, [NotNone] IBufferProtocol/*!*/ b
break;
case FormatType.SizeT:
for (int j = 0; j < curFormat.Count; j++) {
res[res_idx++] = CreateUIntValue(context, ref curIndex, _isLittleEndian, data);
res[res_idx++] = BigIntegerOps.__int__(CreateUIntValue(context, ref curIndex, _isLittleEndian, data));
}
break;
case FormatType.LongLong:
Expand All @@ -349,9 +362,16 @@ public void pack_into(CodeContext/*!*/ context, [NotNone] IBufferProtocol/*!*/ b
res[res_idx++] = BigIntegerOps.__int__(CreateULongValue(context, ref curIndex, _isLittleEndian, data));
}
break;
#if NET6_0_OR_GREATER
case FormatType.Half:
for (int j = 0; j < curFormat.Count; j++) {
res[res_idx++] = (double)CreateHalfValue(context, ref curIndex, _isLittleEndian, data);
}
break;
#endif
case FormatType.Float:
for (int j = 0; j < curFormat.Count; j++) {
res[res_idx++] = CreateFloatValue(context, ref curIndex, _isLittleEndian, data);
res[res_idx++] = (double)CreateFloatValue(context, ref curIndex, _isLittleEndian, data);
}
break;
case FormatType.Double:
Expand Down Expand Up @@ -472,6 +492,12 @@ private static Struct CompileAndCache(CodeContext/*!*/ context, string/*!*/ fmt)
res.Add(new Format(FormatType.UnsignedLongLong, count));
count = 1;
break;
#if NET6_0_OR_GREATER
case 'e': // half
res.Add(new Format(FormatType.Half, count));
count = 1;
break;
#endif
case 'f': // float
res.Add(new Format(FormatType.Float, count));
count = 1;
Expand Down Expand Up @@ -697,6 +723,9 @@ private enum FormatType {

Short,
UnsignedShort,
#if NET6_0_OR_GREATER
Half,
#endif

Int,
UnsignedInt,
Expand Down Expand Up @@ -730,6 +759,9 @@ private static int GetNativeSize(FormatType c) {
return 1;
case FormatType.Short:
case FormatType.UnsignedShort:
#if NET6_0_OR_GREATER
case FormatType.Half:
#endif
return 2;
case FormatType.Int:
case FormatType.UnsignedInt:
Expand Down Expand Up @@ -911,6 +943,18 @@ private static void WriteSignedNetPointer(this MemoryStream res, bool fLittleEnd
res.WritePointer(fLittleEndian, unchecked((ulong)val.ToInt64()));
}

#if NET6_0_OR_GREATER
private static void WriteHalf(this MemoryStream res, bool fLittleEndian, Half val) {
byte[] bytes = BitConverter.GetBytes(val);
if (BitConverter.IsLittleEndian == fLittleEndian) {
res.Write(bytes, 0, bytes.Length);
} else {
res.WriteByte(bytes[1]);
res.WriteByte(bytes[0]);
}
}
#endif

private static void WriteFloat(this MemoryStream res, bool fLittleEndian, float val) {
byte[] bytes = BitConverter.GetBytes(val);
if (BitConverter.IsLittleEndian == fLittleEndian) {
Expand Down Expand Up @@ -1134,7 +1178,7 @@ internal static ulong GetULongLongValue(CodeContext/*!*/ context, int index, obj
internal static double GetDoubleValue(CodeContext/*!*/ context, int index, object[] args) {
object val = GetValue(context, index, args);
if (Converter.TryConvertToDouble(val, out double res)) return res;
throw Error(context, "expected double value");
throw Error(context, "required argument is not a float");
}

internal static IList<byte> GetStringValue(CodeContext/*!*/ context, int index, object[] args) {
Expand Down Expand Up @@ -1194,6 +1238,28 @@ internal static ushort CreateUShortValue(CodeContext/*!*/ context, ref int index
}
}

#if NET6_0_OR_GREATER
internal static Half CreateHalfValue(CodeContext/*!*/ context, ref int index, bool fLittleEndian, IList<byte> data) {
byte[] bytes = new byte[2];
if (fLittleEndian == BitConverter.IsLittleEndian) {
bytes[0] = data[index++];
bytes[1] = data[index++];
} else {
bytes[1] = data[index++];
bytes[0] = data[index++];
}
Half res = BitConverter.ToHalf(bytes, 0);

if (context.LanguageContext.FloatFormat == FloatFormat.Unknown) {
if (Half.IsNaN(res) || Half.IsInfinity(res)) {
throw PythonOps.ValueError("can't unpack IEEE 754 special value on non-IEEE platform");
}
}

return res;
}
#endif

internal static float CreateFloatValue(CodeContext/*!*/ context, ref int index, bool fLittleEndian, IList<byte> data) {
byte[] bytes = new byte[4];
if (fLittleEndian == BitConverter.IsLittleEndian) {
Expand Down
Loading

0 comments on commit 83689ee

Please sign in to comment.