From 808fb0a27213c9be56677ef429910dde1dcac333 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Mon, 11 Jul 2022 16:16:32 +0200 Subject: [PATCH] Implement non-simple String constructors explicitly --- src/runtime/Types/ClassObject.cs | 51 ++++++++++++++++++++++++++++---- tests/test_constructors.py | 17 +++++++++++ 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/runtime/Types/ClassObject.cs b/src/runtime/Types/ClassObject.cs index 70ec53b18..cc42039e8 100644 --- a/src/runtime/Types/ClassObject.cs +++ b/src/runtime/Types/ClassObject.cs @@ -106,24 +106,63 @@ static NewReference tp_new_impl(BorrowedReference tp, BorrowedReference args, Bo /// /// Construct a new .NET String object from Python args + /// + /// This manual implementation of all individual relevant constructors + /// is required because System.String can't be allocated uninitialized. + /// + /// Additionally, it implements `String(pythonStr)` /// private static NewReference NewString(BorrowedReference args, BorrowedReference tp) { - if (Runtime.PyTuple_Size(args) == 1) + var argCount = Runtime.PyTuple_Size(args); + + string? result = null; + if (argCount == 1) { BorrowedReference ob = Runtime.PyTuple_GetItem(args, 0); if (Runtime.PyString_Check(ob)) { if (Runtime.GetManagedString(ob) is string val) - return CLRObject.GetReference(val, tp); + result = val; } + else if (Converter.ToManagedValue(ob, typeof(char[]), out object? arr, false)) + { + result = new String((char[])arr!); + } + } + else if (argCount == 2) + { + BorrowedReference p1 = Runtime.PyTuple_GetItem(args, 0); + BorrowedReference p2 = Runtime.PyTuple_GetItem(args, 1); - // TODO: Initialise using constructors instead - - Exceptions.SetError(Exceptions.TypeError, "no constructors match given arguments"); - return default; + if ( + Converter.ToManagedValue(p1, typeof(char), out object? chr, false) && + Converter.ToManagedValue(p2, typeof(int), out object? count, false) + ) + { + result = new String((char)chr!, (int)count!); + } + } + else if (argCount == 3) + { + BorrowedReference p1 = Runtime.PyTuple_GetItem(args, 0); + BorrowedReference p2 = Runtime.PyTuple_GetItem(args, 1); + BorrowedReference p3 = Runtime.PyTuple_GetItem(args, 2); + + if ( + Converter.ToManagedValue(p1, typeof(char[]), out object? arr, false) && + Converter.ToManagedValue(p2, typeof(int), out object? offset, false) && + Converter.ToManagedValue(p3, typeof(int), out object? length, false) + ) + { + result = new String((char[])arr!, (int)offset!, (int)length!); + } } + if (result != null) + return CLRObject.GetReference(result!, tp); + + Exceptions.SetError(Exceptions.TypeError, "no constructors match given arguments"); return default; } diff --git a/tests/test_constructors.py b/tests/test_constructors.py index 8e7ef2794..6d8f00c12 100644 --- a/tests/test_constructors.py +++ b/tests/test_constructors.py @@ -69,3 +69,20 @@ def test_default_constructor_fallback(): with pytest.raises(TypeError): ob = DefaultConstructorMatching("2") + + +def test_string_constructor(): + from System import String, Char, Array + + ob = String('A', 10) + assert ob == 'A' * 10 + + arr = Array[Char](10) + for i in range(10): + arr[i] = Char(str(i)) + + ob = String(arr) + assert ob == "0123456789" + + ob = String(arr, 5, 4) + assert ob == "5678" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy