1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System;
6 using System.Collections;
7 using System.Collections.Generic;
8 
9 namespace System.Text
10 {
11     public abstract class EncodingProvider
12     {
EncodingProvider()13         public EncodingProvider() { }
GetEncoding(string name)14         public abstract Encoding GetEncoding(string name);
GetEncoding(int codepage)15         public abstract Encoding GetEncoding(int codepage);
16 
17         // GetEncoding should return either valid encoding or null. shouldn't throw any exception except on null name
GetEncoding(string name, EncoderFallback encoderFallback, DecoderFallback decoderFallback)18         public virtual Encoding GetEncoding(string name, EncoderFallback encoderFallback, DecoderFallback decoderFallback)
19         {
20             Encoding enc = GetEncoding(name);
21             if (enc != null)
22             {
23                 enc = (Encoding)GetEncoding(name).Clone();
24                 enc.EncoderFallback = encoderFallback;
25                 enc.DecoderFallback = decoderFallback;
26             }
27 
28             return enc;
29         }
30 
GetEncoding(int codepage, EncoderFallback encoderFallback, DecoderFallback decoderFallback)31         public virtual Encoding GetEncoding(int codepage, EncoderFallback encoderFallback, DecoderFallback decoderFallback)
32         {
33             Encoding enc = GetEncoding(codepage);
34             if (enc != null)
35             {
36                 enc = (Encoding)GetEncoding(codepage).Clone();
37                 enc.EncoderFallback = encoderFallback;
38                 enc.DecoderFallback = decoderFallback;
39             }
40 
41             return enc;
42         }
43 
AddProvider(EncodingProvider provider)44         internal static void AddProvider(EncodingProvider provider)
45         {
46             if (provider == null)
47                 throw new ArgumentNullException(nameof(provider));
48 
49             lock (s_InternalSyncObject)
50             {
51                 if (s_providers == null)
52                 {
53                     s_providers = new EncodingProvider[1] { provider };
54                     return;
55                 }
56 
57                 if (Array.IndexOf(s_providers, provider) >= 0)
58                 {
59                     return;
60                 }
61 
62                 EncodingProvider[] providers = new EncodingProvider[s_providers.Length + 1];
63                 Array.Copy(s_providers, providers, s_providers.Length);
64                 providers[providers.Length - 1] = provider;
65                 s_providers = providers;
66             }
67         }
68 
GetEncodingFromProvider(int codepage)69         internal static Encoding GetEncodingFromProvider(int codepage)
70         {
71             if (s_providers == null)
72                 return null;
73 
74             EncodingProvider[] providers = s_providers;
75             foreach (EncodingProvider provider in providers)
76             {
77                 Encoding enc = provider.GetEncoding(codepage);
78                 if (enc != null)
79                     return enc;
80             }
81 
82             return null;
83         }
84 
GetEncodingFromProvider(string encodingName)85         internal static Encoding GetEncodingFromProvider(string encodingName)
86         {
87             if (s_providers == null)
88                 return null;
89 
90             EncodingProvider[] providers = s_providers;
91             foreach (EncodingProvider provider in providers)
92             {
93                 Encoding enc = provider.GetEncoding(encodingName);
94                 if (enc != null)
95                     return enc;
96             }
97 
98             return null;
99         }
100 
GetEncodingFromProvider(int codepage, EncoderFallback enc, DecoderFallback dec)101         internal static Encoding GetEncodingFromProvider(int codepage, EncoderFallback enc, DecoderFallback dec)
102         {
103             if (s_providers == null)
104                 return null;
105 
106             EncodingProvider[] providers = s_providers;
107             foreach (EncodingProvider provider in providers)
108             {
109                 Encoding encing = provider.GetEncoding(codepage, enc, dec);
110                 if (encing != null)
111                     return encing;
112             }
113 
114             return null;
115         }
116 
GetEncodingFromProvider(string encodingName, EncoderFallback enc, DecoderFallback dec)117         internal static Encoding GetEncodingFromProvider(string encodingName, EncoderFallback enc, DecoderFallback dec)
118         {
119             if (s_providers == null)
120                 return null;
121 
122             EncodingProvider[] providers = s_providers;
123             foreach (EncodingProvider provider in providers)
124             {
125                 Encoding encoding = provider.GetEncoding(encodingName, enc, dec);
126                 if (encoding != null)
127                     return encoding;
128             }
129 
130             return null;
131         }
132 
133         private static Object s_InternalSyncObject = new Object();
134         private static volatile EncodingProvider[] s_providers;
135     }
136 }
137