| File: src\runtime\src\libraries\System.Private.CoreLib\src\System\Text\EncodingProvider.cs | Web Access |
| Project: System.Private.CoreLib.csproj (System.Private.CoreLib) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Threading; namespace System.Text { public abstract class EncodingProvider { private static EncodingProvider[]? s_providers; public EncodingProvider() { } public abstract Encoding? GetEncoding(string name); public abstract Encoding? GetEncoding(int codepage); // GetEncoding should return either valid encoding or null. shouldn't throw any exception except on null name public virtual Encoding? GetEncoding(string name, EncoderFallback encoderFallback, DecoderFallback decoderFallback) { Encoding? enc = GetEncoding(name); if (enc != null) { enc = (Encoding)enc.Clone(); enc.EncoderFallback = encoderFallback; enc.DecoderFallback = decoderFallback; } return enc; } public virtual Encoding? GetEncoding(int codepage, EncoderFallback encoderFallback, DecoderFallback decoderFallback) { Encoding? enc = GetEncoding(codepage); if (enc != null) { enc = (Encoding)enc.Clone(); enc.EncoderFallback = encoderFallback; enc.DecoderFallback = decoderFallback; } return enc; } public virtual IEnumerable<EncodingInfo> GetEncodings() => []; internal static void AddProvider(EncodingProvider provider) { ArgumentNullException.ThrowIfNull(provider); // Few providers are added in a typical app (typically just CodePagesEncodingProvider.Instance), and when they are, // they're generally not added concurrently. So use an optimistic concurrency scheme rather than paying for a lock // object allocation on the startup path. if (s_providers is null && Interlocked.CompareExchange(ref s_providers, [provider], null) is null) { return; } while (true) { EncodingProvider[] providers = s_providers; if (Array.IndexOf(providers, provider) >= 0) { return; } var newProviders = new EncodingProvider[providers.Length + 1]; Array.Copy(providers, newProviders, providers.Length); newProviders[^1] = provider; if (Interlocked.CompareExchange(ref s_providers, newProviders, providers) == providers) { return; } } } internal static Encoding? GetEncodingFromProvider(int codepage) { EncodingProvider[]? providers = s_providers; if (providers == null) return null; foreach (EncodingProvider provider in providers) { Encoding? enc = provider.GetEncoding(codepage); if (enc != null) return enc; } return null; } internal static Dictionary<int, EncodingInfo>? GetEncodingListFromProviders() { EncodingProvider[]? providers = s_providers; if (providers == null) return null; Dictionary<int, EncodingInfo> result = new Dictionary<int, EncodingInfo>(); foreach (EncodingProvider provider in providers) { IEnumerable<EncodingInfo>? encodingInfoList = provider.GetEncodings(); if (encodingInfoList != null) { foreach (EncodingInfo ei in encodingInfoList) { result.TryAdd(ei.CodePage, ei); } } } return result; } internal static Encoding? GetEncodingFromProvider(string encodingName) { EncodingProvider[]? providers = s_providers; if (providers == null) return null; foreach (EncodingProvider provider in providers) { Encoding? enc = provider.GetEncoding(encodingName); if (enc != null) return enc; } return null; } internal static Encoding? GetEncodingFromProvider(int codepage, EncoderFallback enc, DecoderFallback dec) { EncodingProvider[]? providers = s_providers; if (providers == null) return null; foreach (EncodingProvider provider in providers) { Encoding? encoding = provider.GetEncoding(codepage, enc, dec); if (encoding != null) return encoding; } return null; } internal static Encoding? GetEncodingFromProvider(string encodingName, EncoderFallback enc, DecoderFallback dec) { EncodingProvider[]? providers = s_providers; if (providers == null) return null; foreach (EncodingProvider provider in providers) { Encoding? encoding = provider.GetEncoding(encodingName, enc, dec); if (encoding != null) return encoding; } return null; } } }