| File: System\Text\Encodings\Web\TextEncoderSettings.cs | Web Access |
| Project: src\runtime\src\libraries\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj (System.Text.Encodings.Web) |
// 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.Runtime.CompilerServices; using System.Text.Unicode; namespace System.Text.Encodings.Web { /// <summary> /// Represents a filter which allows only certain Unicode code points through. /// </summary> public class TextEncoderSettings { private AllowedBmpCodePointsBitmap _allowedCodePointsBitmap; /// <summary> /// Instantiates an empty filter (allows no code points through by default). /// </summary> public TextEncoderSettings() { } /// <summary> /// Instantiates the filter by cloning the allow list of another <see cref="TextEncoderSettings"/>. /// </summary> public TextEncoderSettings(TextEncoderSettings other) { if (other is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.other); } _allowedCodePointsBitmap = other.GetAllowedCodePointsBitmap(); // copy byval } /// <summary> /// Instantiates the filter where only the character ranges specified by <paramref name="allowedRanges"/> /// are allowed by the filter. /// </summary> public TextEncoderSettings(params UnicodeRange[] allowedRanges) { if (allowedRanges is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.allowedRanges); } AllowRanges(allowedRanges); } /// <summary> /// Allows the character specified by <paramref name="character"/> through the filter. /// </summary> public virtual void AllowCharacter(char character) { _allowedCodePointsBitmap.AllowChar(character); } /// <summary> /// Allows all characters specified by <paramref name="characters"/> through the filter. /// </summary> public virtual void AllowCharacters(params char[] characters) { if (characters is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.characters); } for (int i = 0; i < characters.Length; i++) { _allowedCodePointsBitmap.AllowChar(characters[i]); } } /// <summary> /// Allows all code points specified by <paramref name="codePoints"/>. /// </summary> public virtual void AllowCodePoints(IEnumerable<int> codePoints) { if (codePoints is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.codePoints); } foreach (var allowedCodePoint in codePoints) { // If the code point can't be represented as a BMP character, skip it. if (UnicodeUtility.IsBmpCodePoint((uint)allowedCodePoint)) { _allowedCodePointsBitmap.AllowChar((char)allowedCodePoint); } } } /// <summary> /// Allows all characters specified by <paramref name="range"/> through the filter. /// </summary> public virtual void AllowRange(UnicodeRange range) { if (range is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.range); } int firstCodePoint = range.FirstCodePoint; int rangeSize = range.Length; for (int i = 0; i < rangeSize; i++) { int codePoint = firstCodePoint + i; UnicodeDebug.AssertIsBmpCodePoint((uint)codePoint); // UnicodeRange only supports BMP _allowedCodePointsBitmap.AllowChar((char)codePoint); } } /// <summary> /// Allows all characters specified by <paramref name="ranges"/> through the filter. /// </summary> public virtual void AllowRanges(params UnicodeRange[] ranges) { if (ranges is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.ranges); } for (int i = 0; i < ranges.Length; i++) { AllowRange(ranges[i]); } } /// <summary> /// Resets this settings object by disallowing all characters. /// </summary> public virtual void Clear() { _allowedCodePointsBitmap = default; } /// <summary> /// Disallows the character <paramref name="character"/> through the filter. /// </summary> public virtual void ForbidCharacter(char character) { _allowedCodePointsBitmap.ForbidChar(character); } /// <summary> /// Disallows all characters specified by <paramref name="characters"/> through the filter. /// </summary> public virtual void ForbidCharacters(params char[] characters) { if (characters is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.characters); } for (int i = 0; i < characters.Length; i++) { _allowedCodePointsBitmap.ForbidChar(characters[i]); } } /// <summary> /// Disallows all characters specified by <paramref name="range"/> through the filter. /// </summary> public virtual void ForbidRange(UnicodeRange range) { if (range is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.range); } int firstCodePoint = range.FirstCodePoint; int rangeSize = range.Length; for (int i = 0; i < rangeSize; i++) { int codePoint = firstCodePoint + i; UnicodeDebug.AssertIsBmpCodePoint((uint)codePoint); // UnicodeRange only supports BMP _allowedCodePointsBitmap.ForbidChar((char)codePoint); } } /// <summary> /// Disallows all characters specified by <paramref name="ranges"/> through the filter. /// </summary> public virtual void ForbidRanges(params UnicodeRange[] ranges) { if (ranges is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.ranges); } for (int i = 0; i < ranges.Length; i++) { ForbidRange(ranges[i]); } } /// <summary> /// Gets an enumeration of all allowed code points. /// </summary> public virtual IEnumerable<int> GetAllowedCodePoints() { for (int i = 0; i <= char.MaxValue; i++) { if (_allowedCodePointsBitmap.IsCharAllowed((char)i)) { yield return i; } } } /// <summary> /// Retrieves the bitmap of allowed characters from this settings object. /// The data is returned readonly byref. /// </summary> internal ref readonly AllowedBmpCodePointsBitmap GetAllowedCodePointsBitmap() { if (GetType() == typeof(TextEncoderSettings)) { return ref _allowedCodePointsBitmap; } else { // Somebody may have overridden GetAllowedCodePoints, and we need to honor that. // Fabricate a new bitmap and populate it from the virtual overrides. StrongBox<AllowedBmpCodePointsBitmap> newBitmap = new StrongBox<AllowedBmpCodePointsBitmap>(); foreach (int allowedCodePoint in GetAllowedCodePoints()) { if ((uint)allowedCodePoint <= char.MaxValue) { newBitmap.Value.AllowChar((char)allowedCodePoint); } } return ref newBitmap.Value; } } } }