X Tutup
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; namespace Python.Runtime { static partial class InternString { private static readonly Dictionary _string2interns = new(); private static readonly Dictionary _intern2strings = new(); const BindingFlags PyIdentifierFieldFlags = BindingFlags.Static | BindingFlags.NonPublic; static InternString() { var identifierNames = typeof(PyIdentifier).GetFields(PyIdentifierFieldFlags) .Select(fi => fi.Name.Substring(1)); var validNames = new HashSet(identifierNames); if (validNames.Count != _builtinNames.Length) { throw new InvalidOperationException("Identifiers args not matching"); } foreach (var name in _builtinNames) { if (!validNames.Contains(name)) { throw new InvalidOperationException($"{name} is not declared"); } } } public static void Initialize() { Debug.Assert(_string2interns.Count == 0); Type type = typeof(PyIdentifier); foreach (string name in _builtinNames) { NewReference pyStr = Runtime.PyUnicode_InternFromString(name); var op = new PyString(pyStr.StealOrThrow()); Debug.Assert(name == op.As()); SetIntern(name, op); var field = type.GetField("f" + name, PyIdentifierFieldFlags)!; field.SetValue(null, op.DangerousGetAddressOrNull()); } } public static void Shutdown() { foreach (var entry in _string2interns) { var field = typeof(PyIdentifier).GetField("f" + entry.Value, PyIdentifierFieldFlags)!; entry.Value.Dispose(); field.SetValue(null, IntPtr.Zero); } _string2interns.Clear(); _intern2strings.Clear(); } public static string? GetManagedString(BorrowedReference op) { if (TryGetInterned(op, out string s)) { return s; } return Runtime.GetManagedString(op); } public static bool TryGetInterned(BorrowedReference op, out string s) { return _intern2strings.TryGetValue(op.DangerousGetAddress(), out s); } private static void SetIntern(string s, PyString op) { _string2interns.Add(s, op); _intern2strings.Add(op.Reference.DangerousGetAddress(), s); } } }
X Tutup