1 //------------------------------------------------------------------------------
2 // <copyright file="WebUtility.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
7 // Don't entity encode high chars (160 to 256), to fix bugs VSWhidbey 85857/111927
9 #define ENTITY_ENCODE_HIGH_ASCII_CHARS
11 namespace System.Net {
13 using System.Collections.Generic;
15 using System.Configuration;
17 using System.Diagnostics;
18 using System.Diagnostics.CodeAnalysis;
19 using System.Globalization;
21 using System.Net.Configuration;
22 using System.Runtime.Versioning;
25 using System.Security;
28 public static class WebUtility
30 // some consts copied from Char / CharUnicodeInfo since we don't have friend access to those types
31 private const char HIGH_SURROGATE_START = '\uD800';
32 private const char LOW_SURROGATE_START = '\uDC00';
33 private const char LOW_SURROGATE_END = '\uDFFF';
34 private const int UNICODE_PLANE00_END = 0x00FFFF;
35 private const int UNICODE_PLANE01_START = 0x10000;
36 private const int UNICODE_PLANE16_END = 0x10FFFF;
38 private const int UnicodeReplacementChar = '\uFFFD';
40 private static readonly char[] _htmlEntityEndingChars = new char[] { ';', '&' };
42 private static volatile UnicodeDecodingConformance _htmlDecodeConformance = UnicodeDecodingConformance.Auto;
43 private static volatile UnicodeEncodingConformance _htmlEncodeConformance = UnicodeEncodingConformance.Auto;
45 #region HtmlEncode / HtmlDecode methods
47 public static string HtmlEncode(string value) {
48 if (String.IsNullOrEmpty(value)) {
52 // Don't create string writer if we don't have nothing to encode
53 int index = IndexOfHtmlEncodingChars(value, 0);
58 StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
59 HtmlEncode(value, writer);
60 return writer.ToString();
64 [SecuritySafeCritical]
66 public static unsafe void HtmlEncode(string value, TextWriter output) {
71 throw new ArgumentNullException("output");
74 int index = IndexOfHtmlEncodingChars(value, 0);
80 Debug.Assert(0 <= index && index <= value.Length, "0 <= index && index <= value.Length");
82 UnicodeEncodingConformance encodeConformance = HtmlEncodeConformance;
83 int cch = value.Length - index;
84 fixed (char* str = value) {
90 for (; cch > 0; cch--, pch++) {
101 output.Write(""");
104 output.Write("'");
107 output.Write("&");
115 int valueToEncode = -1; // set to >= 0 if needs to be encoded
117 #if ENTITY_ENCODE_HIGH_ASCII_CHARS
120 // MS starts encoding with &# from 160 and stops at 255.
121 // We don't do that. One reason is the 65308/65310 unicode
122 // characters that look like '<' and '>'.
123 if (ch >= 160 && !char.IsSurrogate (ch)) {
126 if (ch >= 160 && ch < 256) {
127 // The seemingly arbitrary 160 comes from RFC
131 #endif // ENTITY_ENCODE_HIGH_ASCII_CHARS
132 if (encodeConformance == UnicodeEncodingConformance.Strict && Char.IsSurrogate(ch)) {
133 int scalarValue = GetNextUnicodeScalarValueFromUtf16Surrogate(ref pch, ref cch);
134 if (scalarValue >= UNICODE_PLANE01_START) {
135 valueToEncode = scalarValue;
138 // Don't encode BMP characters (like U+FFFD) since they wouldn't have
139 // been encoded if explicitly present in the string anyway.
140 ch = (char)scalarValue;
144 if (valueToEncode >= 0) {
145 // value needs to be encoded
147 output.Write(valueToEncode.ToString(NumberFormatInfo.InvariantInfo));
151 // write out the character directly
159 public static string HtmlDecode(string value) {
160 if (String.IsNullOrEmpty(value)) {
164 // Don't create string writer if we don't have nothing to encode
165 if (!StringRequiresHtmlDecoding(value)) {
169 StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
170 HtmlDecode(value, writer);
171 return writer.ToString();
174 [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.UInt16.TryParse(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.UInt16@)", Justification="UInt16.TryParse guarantees that result is zero if the parse fails.")]
175 public static void HtmlDecode(string value, TextWriter output) {
179 if (output == null) {
180 throw new ArgumentNullException("output");
183 if (!StringRequiresHtmlDecoding(value)) {
184 output.Write(value); // good as is
188 UnicodeDecodingConformance decodeConformance = HtmlDecodeConformance;
189 int l = value.Length;
190 for (int i = 0; i < l; i++) {
194 // We found a '&'. Now look for the next ';' or '&'. The idea is that
195 // if we find another '&' before finding a ';', then this is not an entity,
196 // and the next '&' might start a real entity (VSWhidbey 275184)
197 int index = value.IndexOfAny(_htmlEntityEndingChars, i + 1);
198 if (index > 0 && value[index] == ';') {
199 string entity = value.Substring(i + 1, index - i - 1);
201 if (entity.Length > 1 && entity[0] == '#') {
202 // The # syntax can be in decimal or hex, e.g.
203 // å --> decimal
204 // å --> same char in hex
205 // See http://www.w3.org/TR/REC-html40/charset.html#entities
207 bool parsedSuccessfully;
209 if (entity[1] == 'x' || entity[1] == 'X') {
210 parsedSuccessfully = UInt32.TryParse(entity.Substring(2), NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out parsedValue);
213 parsedSuccessfully = UInt32.TryParse(entity.Substring(1), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out parsedValue);
216 if (parsedSuccessfully) {
217 switch (decodeConformance) {
218 case UnicodeDecodingConformance.Strict:
219 // decoded character must be U+0000 .. U+10FFFF, excluding surrogates
220 parsedSuccessfully = ((parsedValue < HIGH_SURROGATE_START) || (LOW_SURROGATE_END < parsedValue && parsedValue <= UNICODE_PLANE16_END));
223 case UnicodeDecodingConformance.Compat:
224 // decoded character must be U+0001 .. U+FFFF
225 // null chars disallowed for compat with 4.0
226 parsedSuccessfully = (0 < parsedValue && parsedValue <= UNICODE_PLANE00_END);
229 case UnicodeDecodingConformance.Loose:
230 // decoded character must be U+0000 .. U+10FFFF
231 parsedSuccessfully = (parsedValue <= UNICODE_PLANE16_END);
235 Debug.Assert(false, "Should never get here!");
236 parsedSuccessfully = false;
241 if (parsedSuccessfully) {
242 if (parsedValue <= UNICODE_PLANE00_END) {
244 output.Write((char)parsedValue);
248 char leadingSurrogate, trailingSurrogate;
249 ConvertSmpToUtf16(parsedValue, out leadingSurrogate, out trailingSurrogate);
250 output.Write(leadingSurrogate);
251 output.Write(trailingSurrogate);
254 i = index; // already looked at everything until semicolon
259 i = index; // already looked at everything until semicolon
261 char entityChar = HtmlEntities.Lookup(entity);
262 if (entityChar != (char)0) {
267 output.Write(entity);
281 [SecuritySafeCritical]
283 private static unsafe int IndexOfHtmlEncodingChars(string s, int startPos) {
284 Debug.Assert(0 <= startPos && startPos <= s.Length, "0 <= startPos && startPos <= s.Length");
286 UnicodeEncodingConformance encodeConformance = HtmlEncodeConformance;
287 int cch = s.Length - startPos;
288 fixed (char* str = s) {
289 for (char* pch = &str[startPos]; cch > 0; pch++, cch--) {
298 return s.Length - cch;
301 #if ENTITY_ENCODE_HIGH_ASCII_CHARS
307 return s.Length - cch;
309 #endif // ENTITY_ENCODE_HIGH_ASCII_CHARS
310 else if (encodeConformance == UnicodeEncodingConformance.Strict && Char.IsSurrogate(ch)) {
311 return s.Length - cch;
319 private static UnicodeDecodingConformance HtmlDecodeConformance {
321 if (_htmlDecodeConformance != UnicodeDecodingConformance.Auto) {
322 return _htmlDecodeConformance;
325 UnicodeDecodingConformance defaultDecodeConformance = (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) ? UnicodeDecodingConformance.Strict : UnicodeDecodingConformance.Compat;
326 UnicodeDecodingConformance decodingConformance = defaultDecodeConformance;
328 #if !FEATURE_NETCORE && !MOBILE
331 decodingConformance = SettingsSectionInternal.Section.WebUtilityUnicodeDecodingConformance;
332 // Normalize conformance settings (turn 'Auto' into the actual setting)
333 if (decodingConformance <= UnicodeDecodingConformance.Auto || decodingConformance > UnicodeDecodingConformance.Loose) {
334 decodingConformance = defaultDecodeConformance;
337 catch (ConfigurationException) {
338 // Continue with default values
339 // HtmlDecode and related methods can still be called and format the error page intended for the client
340 // No need to retry again to initialize from the config in case of config errors
341 decodingConformance = defaultDecodeConformance;
345 // ASP.NET uses own ConfigurationManager which can throw in more situations than config errors (i.e. BadRequest)
346 // It's ok to swallow the exception here and continue using the default value
347 // Try to initialize again the next time
348 return defaultDecodeConformance;
351 _htmlDecodeConformance = decodingConformance;
353 return _htmlDecodeConformance;
357 private static UnicodeEncodingConformance HtmlEncodeConformance {
359 if (_htmlEncodeConformance != UnicodeEncodingConformance.Auto) {
360 return _htmlEncodeConformance;
363 UnicodeEncodingConformance defaultEncodeConformance = (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) ? UnicodeEncodingConformance.Strict : UnicodeEncodingConformance.Compat;
364 UnicodeEncodingConformance encodingConformance = defaultEncodeConformance;
366 #if !FEATURE_NETCORE && !MOBILE
369 encodingConformance = SettingsSectionInternal.Section.WebUtilityUnicodeEncodingConformance;
371 // Normalize conformance settings (turn 'Auto' into the actual setting)
372 if (encodingConformance <= UnicodeEncodingConformance.Auto || encodingConformance > UnicodeEncodingConformance.Compat) {
373 encodingConformance = defaultEncodeConformance;
376 catch (ConfigurationException) {
377 // Continue with default values
378 // HtmlEncode and related methods can still be called and format the error page intended for the client
379 // No need to retry again to initialize from the config in case of config errors
380 encodingConformance = defaultEncodeConformance;
384 // ASP.NET uses own ConfigurationManager which can throw in more situations than config errors (i.e. BadRequest)
385 // It's ok to swallow the exception here and continue using the default value
386 // Try to initialize again the next time
387 return defaultEncodeConformance;
390 _htmlEncodeConformance = encodingConformance;
392 return _htmlEncodeConformance;
398 #region UrlEncode implementation
400 // *** Source: alm/tfs_core/Framework/Common/UriUtility/HttpUtility.cs
401 // This specific code was copied from above ASP.NET codebase.
403 private static byte[] UrlEncode(byte[] bytes, int offset, int count, bool alwaysCreateNewReturnValue)
405 byte[] encoded = UrlEncode(bytes, offset, count);
407 return (alwaysCreateNewReturnValue && (encoded != null) && (encoded == bytes))
408 ? (byte[])encoded.Clone()
412 private static byte[] UrlEncode(byte[] bytes, int offset, int count)
414 if (!ValidateUrlEncodingParameters(bytes, offset, count))
423 for (int i = 0; i < count; i++)
425 char ch = (char)bytes[offset + i];
429 else if (!IsUrlSafeChar(ch))
433 // nothing to expand?
434 if (cSpaces == 0 && cUnsafe == 0) {
435 // DevDiv 912606: respect "offset" and "count"
436 if (0 == offset && bytes.Length == count) {
440 var subarray = new byte[count];
441 Buffer.BlockCopy(bytes, offset, subarray, 0, count);
446 // expand not 'safe' characters into %XX, spaces to +s
447 byte[] expandedBytes = new byte[count + cUnsafe * 2];
450 for (int i = 0; i < count; i++)
452 byte b = bytes[offset + i];
455 if (IsUrlSafeChar(ch))
457 expandedBytes[pos++] = b;
461 expandedBytes[pos++] = (byte)'+';
465 expandedBytes[pos++] = (byte)'%';
466 expandedBytes[pos++] = (byte)IntToHex((b >> 4) & 0xf);
467 expandedBytes[pos++] = (byte)IntToHex(b & 0x0f);
471 return expandedBytes;
476 #region UrlEncode public methods
478 [SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings", Justification="Already shipped public API; code moved here as part of API consolidation")]
479 public static string UrlEncode(string value)
484 byte[] bytes = Encoding.UTF8.GetBytes(value);
485 return Encoding.UTF8.GetString(UrlEncode(bytes, 0, bytes.Length, false /* alwaysCreateNewReturnValue */));
488 public static byte[] UrlEncodeToBytes(byte[] value, int offset, int count)
490 return UrlEncode(value, offset, count, true /* alwaysCreateNewReturnValue */);
495 #region UrlDecode implementation
497 // *** Source: alm/tfs_core/Framework/Common/UriUtility/HttpUtility.cs
498 // This specific code was copied from above ASP.NET codebase.
499 // Changes done - Removed the logic to handle %Uxxxx as it is not standards compliant.
501 private static string UrlDecodeInternal(string value, Encoding encoding)
508 int count = value.Length;
509 UrlDecoder helper = new UrlDecoder(count, encoding);
511 // go through the string's chars collapsing %XX and
512 // appending each char as char, with exception of %XX constructs
513 // that are appended as bytes
515 for (int pos = 0; pos < count; pos++)
517 char ch = value[pos];
523 else if (ch == '%' && pos < count - 2)
525 int h1 = HexToInt(value[pos + 1]);
526 int h2 = HexToInt(value[pos + 2]);
528 if (h1 >= 0 && h2 >= 0)
529 { // valid 2 hex chars
530 byte b = (byte)((h1 << 4) | h2);
539 if ((ch & 0xFF80) == 0)
540 helper.AddByte((byte)ch); // 7 bit have to go as bytes because of Unicode
545 return helper.GetString();
548 private static byte[] UrlDecodeInternal(byte[] bytes, int offset, int count)
550 if (!ValidateUrlEncodingParameters(bytes, offset, count))
555 int decodedBytesCount = 0;
556 byte[] decodedBytes = new byte[count];
558 for (int i = 0; i < count; i++)
560 int pos = offset + i;
567 else if (b == '%' && i < count - 2)
569 int h1 = HexToInt((char)bytes[pos + 1]);
570 int h2 = HexToInt((char)bytes[pos + 2]);
572 if (h1 >= 0 && h2 >= 0)
573 { // valid 2 hex chars
574 b = (byte)((h1 << 4) | h2);
579 decodedBytes[decodedBytesCount++] = b;
582 if (decodedBytesCount < decodedBytes.Length)
584 byte[] newDecodedBytes = new byte[decodedBytesCount];
585 Array.Copy(decodedBytes, newDecodedBytes, decodedBytesCount);
586 decodedBytes = newDecodedBytes;
594 #region UrlDecode public methods
597 [SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings", Justification="Already shipped public API; code moved here as part of API consolidation")]
598 public static string UrlDecode(string encodedValue)
600 if (encodedValue == null)
603 return UrlDecodeInternal(encodedValue, Encoding.UTF8);
606 public static byte[] UrlDecodeToBytes(byte[] encodedValue, int offset, int count)
608 return UrlDecodeInternal(encodedValue, offset, count);
613 #region Helper methods
615 // similar to Char.ConvertFromUtf32, but doesn't check arguments or generate strings
616 // input is assumed to be an SMP character
617 private static void ConvertSmpToUtf16(uint smpChar, out char leadingSurrogate, out char trailingSurrogate) {
618 Debug.Assert(UNICODE_PLANE01_START <= smpChar && smpChar <= UNICODE_PLANE16_END);
620 int utf32 = (int)(smpChar - UNICODE_PLANE01_START);
621 leadingSurrogate = (char)((utf32 / 0x400) + HIGH_SURROGATE_START);
622 trailingSurrogate = (char)((utf32 % 0x400) + LOW_SURROGATE_START);
626 [SecuritySafeCritical]
628 private static unsafe int GetNextUnicodeScalarValueFromUtf16Surrogate(ref char* pch, ref int charsRemaining) {
630 Debug.Assert(charsRemaining >= 1);
631 Debug.Assert(Char.IsSurrogate(*pch));
633 if (charsRemaining <= 1) {
634 // not enough characters remaining to resurrect the original scalar value
635 return UnicodeReplacementChar;
638 char leadingSurrogate = pch[0];
639 char trailingSurrogate = pch[1];
641 if (Char.IsSurrogatePair(leadingSurrogate, trailingSurrogate)) {
642 // we're going to consume an extra char
646 // below code is from Char.ConvertToUtf32, but without the checks (since we just performed them)
647 return (((leadingSurrogate - HIGH_SURROGATE_START) * 0x400) + (trailingSurrogate - LOW_SURROGATE_START) + UNICODE_PLANE01_START);
650 // unmatched surrogate
651 return UnicodeReplacementChar;
655 private static int HexToInt(char h)
657 return (h >= '0' && h <= '9') ? h - '0' :
658 (h >= 'a' && h <= 'f') ? h - 'a' + 10 :
659 (h >= 'A' && h <= 'F') ? h - 'A' + 10 :
663 private static char IntToHex(int n)
665 Debug.Assert(n < 0x10);
668 return (char)(n + (int)'0');
670 return (char)(n - 10 + (int)'A');
673 // Set of safe chars, from RFC 1738.4 minus '+'
674 private static bool IsUrlSafeChar(char ch)
676 if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
694 private static bool ValidateUrlEncodingParameters(byte[] bytes, int offset, int count)
696 if (bytes == null && count == 0)
700 throw new ArgumentNullException("bytes");
702 if (offset < 0 || offset > bytes.Length)
704 throw new ArgumentOutOfRangeException("offset");
706 if (count < 0 || offset + count > bytes.Length)
708 throw new ArgumentOutOfRangeException("count");
714 private static bool StringRequiresHtmlDecoding(string s) {
715 if (HtmlDecodeConformance == UnicodeDecodingConformance.Compat) {
716 // this string requires html decoding only if it contains '&'
717 return (s.IndexOf('&') >= 0);
720 // this string requires html decoding if it contains '&' or a surrogate character
721 for (int i = 0; i < s.Length; i++) {
723 if (c == '&' || Char.IsSurrogate(c)) {
733 #region UrlDecoder nested class
735 // *** Source: alm/tfs_core/Framework/Common/UriUtility/HttpUtility.cs
736 // This specific code was copied from above ASP.NET codebase.
738 // Internal class to facilitate URL decoding -- keeps char buffer and byte buffer, allows appending of either chars or bytes
739 private class UrlDecoder
741 private int _bufferSize;
743 // Accumulate characters in a special array
744 private int _numChars;
745 private char[] _charBuffer;
747 // Accumulate bytes for decoding into characters in a special array
748 private int _numBytes;
749 private byte[] _byteBuffer;
751 // Encoding to convert chars to bytes
752 private Encoding _encoding;
754 private void FlushBytes()
758 _numChars += _encoding.GetChars(_byteBuffer, 0, _numBytes, _charBuffer, _numChars);
763 internal UrlDecoder(int bufferSize, Encoding encoding)
765 _bufferSize = bufferSize;
766 _encoding = encoding;
768 _charBuffer = new char[bufferSize];
769 // byte buffer created on demand
772 internal void AddChar(char ch)
777 _charBuffer[_numChars++] = ch;
780 internal void AddByte(byte b)
782 if (_byteBuffer == null)
783 _byteBuffer = new byte[_bufferSize];
785 _byteBuffer[_numBytes++] = b;
788 internal String GetString()
794 return new String(_charBuffer, 0, _numChars);
802 #region HtmlEntities nested class
804 // helper class for lookup of HTML encoding entities
805 private static class HtmlEntities {
808 public static char Lookup (string entity)
810 var token = CalculateKeyValue (entity);
815 var idx = Array.BinarySearch (entities, token);
820 return entities_values [idx];
823 static long CalculateKeyValue (string s)
829 for (int i = 0; i < s.Length; ++i) {
831 if (ch > 'z' || ch < '0')
834 key |= ch << ((7 - i) * 8);
841 static readonly long[] entities = new long[] {
842 (long)'A' << 56 | (long)'E' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
843 (long)'A' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
844 (long)'A' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
845 (long)'A' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
846 (long)'A' << 56 | (long)'l' << 48 | (long)'p' << 40 | (long)'h' << 32 | (long)'a' << 24,
847 (long)'A' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'g' << 24,
848 (long)'A' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
849 (long)'A' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
850 (long)'B' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
851 (long)'C' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'d' << 32 | (long)'i' << 24 | (long)'l' << 16,
852 (long)'C' << 56 | (long)'h' << 48 | (long)'i' << 40,
853 (long)'D' << 56 | (long)'a' << 48 | (long)'g' << 40 | (long)'g' << 32 | (long)'e' << 24 | (long)'r' << 16,
854 (long)'D' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'t' << 32 | (long)'a' << 24,
855 (long)'E' << 56 | (long)'T' << 48 | (long)'H' << 40,
856 (long)'E' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
857 (long)'E' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
858 (long)'E' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
859 (long)'E' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
860 (long)'E' << 56 | (long)'t' << 48 | (long)'a' << 40,
861 (long)'E' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
862 (long)'G' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'m' << 32 | (long)'a' << 24,
863 (long)'I' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
864 (long)'I' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
865 (long)'I' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
866 (long)'I' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'a' << 32,
867 (long)'I' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
868 (long)'K' << 56 | (long)'a' << 48 | (long)'p' << 40 | (long)'p' << 32 | (long)'a' << 24,
869 (long)'L' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'b' << 32 | (long)'d' << 24 | (long)'a' << 16,
870 (long)'M' << 56 | (long)'u' << 48,
871 (long)'N' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
872 (long)'N' << 56 | (long)'u' << 48,
873 (long)'O' << 56 | (long)'E' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
874 (long)'O' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
875 (long)'O' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
876 (long)'O' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
877 (long)'O' << 56 | (long)'m' << 48 | (long)'e' << 40 | (long)'g' << 32 | (long)'a' << 24,
878 (long)'O' << 56 | (long)'m' << 48 | (long)'i' << 40 | (long)'c' << 32 | (long)'r' << 24 | (long)'o' << 16 | (long)'n' << 8,
879 (long)'O' << 56 | (long)'s' << 48 | (long)'l' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'h' << 16,
880 (long)'O' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
881 (long)'O' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
882 (long)'P' << 56 | (long)'h' << 48 | (long)'i' << 40,
883 (long)'P' << 56 | (long)'i' << 48,
884 (long)'P' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24,
885 (long)'P' << 56 | (long)'s' << 48 | (long)'i' << 40,
886 (long)'R' << 56 | (long)'h' << 48 | (long)'o' << 40,
887 (long)'S' << 56 | (long)'c' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'o' << 24 | (long)'n' << 16,
888 (long)'S' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24,
889 (long)'T' << 56 | (long)'H' << 48 | (long)'O' << 40 | (long)'R' << 32 | (long)'N' << 24,
890 (long)'T' << 56 | (long)'a' << 48 | (long)'u' << 40,
891 (long)'T' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24,
892 (long)'U' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
893 (long)'U' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
894 (long)'U' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
895 (long)'U' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
896 (long)'U' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
897 (long)'X' << 56 | (long)'i' << 48,
898 (long)'Y' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
899 (long)'Y' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
900 (long)'Z' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
901 (long)'a' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
902 (long)'a' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
903 (long)'a' << 56 | (long)'c' << 48 | (long)'u' << 40 | (long)'t' << 32 | (long)'e' << 24,
904 (long)'a' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
905 (long)'a' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
906 (long)'a' << 56 | (long)'l' << 48 | (long)'e' << 40 | (long)'f' << 32 | (long)'s' << 24 | (long)'y' << 16 | (long)'m' << 8,
907 (long)'a' << 56 | (long)'l' << 48 | (long)'p' << 40 | (long)'h' << 32 | (long)'a' << 24,
908 (long)'a' << 56 | (long)'m' << 48 | (long)'p' << 40,
909 (long)'a' << 56 | (long)'n' << 48 | (long)'d' << 40,
910 (long)'a' << 56 | (long)'n' << 48 | (long)'g' << 40,
911 (long)'a' << 56 | (long)'p' << 48 | (long)'o' << 40 | (long)'s' << 32,
912 (long)'a' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'g' << 24,
913 (long)'a' << 56 | (long)'s' << 48 | (long)'y' << 40 | (long)'m' << 32 | (long)'p' << 24,
914 (long)'a' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
915 (long)'a' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
916 (long)'b' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
917 (long)'b' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
918 (long)'b' << 56 | (long)'r' << 48 | (long)'v' << 40 | (long)'b' << 32 | (long)'a' << 24 | (long)'r' << 16,
919 (long)'b' << 56 | (long)'u' << 48 | (long)'l' << 40 | (long)'l' << 32,
920 (long)'c' << 56 | (long)'a' << 48 | (long)'p' << 40,
921 (long)'c' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'d' << 32 | (long)'i' << 24 | (long)'l' << 16,
922 (long)'c' << 56 | (long)'e' << 48 | (long)'d' << 40 | (long)'i' << 32 | (long)'l' << 24,
923 (long)'c' << 56 | (long)'e' << 48 | (long)'n' << 40 | (long)'t' << 32,
924 (long)'c' << 56 | (long)'h' << 48 | (long)'i' << 40,
925 (long)'c' << 56 | (long)'i' << 48 | (long)'r' << 40 | (long)'c' << 32,
926 (long)'c' << 56 | (long)'l' << 48 | (long)'u' << 40 | (long)'b' << 32 | (long)'s' << 24,
927 (long)'c' << 56 | (long)'o' << 48 | (long)'n' << 40 | (long)'g' << 32,
928 (long)'c' << 56 | (long)'o' << 48 | (long)'p' << 40 | (long)'y' << 32,
929 (long)'c' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'r' << 24,
930 (long)'c' << 56 | (long)'u' << 48 | (long)'p' << 40,
931 (long)'c' << 56 | (long)'u' << 48 | (long)'r' << 40 | (long)'r' << 32 | (long)'e' << 24 | (long)'n' << 16,
932 (long)'d' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
933 (long)'d' << 56 | (long)'a' << 48 | (long)'g' << 40 | (long)'g' << 32 | (long)'e' << 24 | (long)'r' << 16,
934 (long)'d' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
935 (long)'d' << 56 | (long)'e' << 48 | (long)'g' << 40,
936 (long)'d' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'t' << 32 | (long)'a' << 24,
937 (long)'d' << 56 | (long)'i' << 48 | (long)'a' << 40 | (long)'m' << 32 | (long)'s' << 24,
938 (long)'d' << 56 | (long)'i' << 48 | (long)'v' << 40 | (long)'i' << 32 | (long)'d' << 24 | (long)'e' << 16,
939 (long)'e' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
940 (long)'e' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
941 (long)'e' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
942 (long)'e' << 56 | (long)'m' << 48 | (long)'p' << 40 | (long)'t' << 32 | (long)'y' << 24,
943 (long)'e' << 56 | (long)'m' << 48 | (long)'s' << 40 | (long)'p' << 32,
944 (long)'e' << 56 | (long)'n' << 48 | (long)'s' << 40 | (long)'p' << 32,
945 (long)'e' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
946 (long)'e' << 56 | (long)'q' << 48 | (long)'u' << 40 | (long)'i' << 32 | (long)'v' << 24,
947 (long)'e' << 56 | (long)'t' << 48 | (long)'a' << 40,
948 (long)'e' << 56 | (long)'t' << 48 | (long)'h' << 40,
949 (long)'e' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
950 (long)'e' << 56 | (long)'u' << 48 | (long)'r' << 40 | (long)'o' << 32,
951 (long)'e' << 56 | (long)'x' << 48 | (long)'i' << 40 | (long)'s' << 32 | (long)'t' << 24,
952 (long)'f' << 56 | (long)'n' << 48 | (long)'o' << 40 | (long)'f' << 32,
953 (long)'f' << 56 | (long)'o' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'l' << 24 | (long)'l' << 16,
954 (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'1' << 24 | (long)'2' << 16,
955 (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'1' << 24 | (long)'4' << 16,
956 (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'3' << 24 | (long)'4' << 16,
957 (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'l' << 24,
958 (long)'g' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'m' << 32 | (long)'a' << 24,
959 (long)'g' << 56 | (long)'e' << 48,
960 (long)'g' << 56 | (long)'t' << 48,
961 (long)'h' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
962 (long)'h' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
963 (long)'h' << 56 | (long)'e' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'t' << 24 | (long)'s' << 16,
964 (long)'h' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'l' << 32 | (long)'i' << 24 | (long)'p' << 16,
965 (long)'i' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
966 (long)'i' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
967 (long)'i' << 56 | (long)'e' << 48 | (long)'x' << 40 | (long)'c' << 32 | (long)'l' << 24,
968 (long)'i' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
969 (long)'i' << 56 | (long)'m' << 48 | (long)'a' << 40 | (long)'g' << 32 | (long)'e' << 24,
970 (long)'i' << 56 | (long)'n' << 48 | (long)'f' << 40 | (long)'i' << 32 | (long)'n' << 24,
971 (long)'i' << 56 | (long)'n' << 48 | (long)'t' << 40,
972 (long)'i' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'a' << 32,
973 (long)'i' << 56 | (long)'q' << 48 | (long)'u' << 40 | (long)'e' << 32 | (long)'s' << 24 | (long)'t' << 16,
974 (long)'i' << 56 | (long)'s' << 48 | (long)'i' << 40 | (long)'n' << 32,
975 (long)'i' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
976 (long)'k' << 56 | (long)'a' << 48 | (long)'p' << 40 | (long)'p' << 32 | (long)'a' << 24,
977 (long)'l' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
978 (long)'l' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'b' << 32 | (long)'d' << 24 | (long)'a' << 16,
979 (long)'l' << 56 | (long)'a' << 48 | (long)'n' << 40 | (long)'g' << 32,
980 (long)'l' << 56 | (long)'a' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
981 (long)'l' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
982 (long)'l' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'i' << 32 | (long)'l' << 24,
983 (long)'l' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
984 (long)'l' << 56 | (long)'e' << 48,
985 (long)'l' << 56 | (long)'f' << 48 | (long)'l' << 40 | (long)'o' << 32 | (long)'o' << 24 | (long)'r' << 16,
986 (long)'l' << 56 | (long)'o' << 48 | (long)'w' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'t' << 16,
987 (long)'l' << 56 | (long)'o' << 48 | (long)'z' << 40,
988 (long)'l' << 56 | (long)'r' << 48 | (long)'m' << 40,
989 (long)'l' << 56 | (long)'s' << 48 | (long)'a' << 40 | (long)'q' << 32 | (long)'u' << 24 | (long)'o' << 16,
990 (long)'l' << 56 | (long)'s' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
991 (long)'l' << 56 | (long)'t' << 48,
992 (long)'m' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'r' << 32,
993 (long)'m' << 56 | (long)'d' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'h' << 24,
994 (long)'m' << 56 | (long)'i' << 48 | (long)'c' << 40 | (long)'r' << 32 | (long)'o' << 24,
995 (long)'m' << 56 | (long)'i' << 48 | (long)'d' << 40 | (long)'d' << 32 | (long)'o' << 24 | (long)'t' << 16,
996 (long)'m' << 56 | (long)'i' << 48 | (long)'n' << 40 | (long)'u' << 32 | (long)'s' << 24,
997 (long)'m' << 56 | (long)'u' << 48,
998 (long)'n' << 56 | (long)'a' << 48 | (long)'b' << 40 | (long)'l' << 32 | (long)'a' << 24,
999 (long)'n' << 56 | (long)'b' << 48 | (long)'s' << 40 | (long)'p' << 32,
1000 (long)'n' << 56 | (long)'d' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'h' << 24,
1001 (long)'n' << 56 | (long)'e' << 48,
1002 (long)'n' << 56 | (long)'i' << 48,
1003 (long)'n' << 56 | (long)'o' << 48 | (long)'t' << 40,
1004 (long)'n' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'i' << 32 | (long)'n' << 24,
1005 (long)'n' << 56 | (long)'s' << 48 | (long)'u' << 40 | (long)'b' << 32,
1006 (long)'n' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
1007 (long)'n' << 56 | (long)'u' << 48,
1008 (long)'o' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
1009 (long)'o' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
1010 (long)'o' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
1011 (long)'o' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
1012 (long)'o' << 56 | (long)'l' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'e' << 24,
1013 (long)'o' << 56 | (long)'m' << 48 | (long)'e' << 40 | (long)'g' << 32 | (long)'a' << 24,
1014 (long)'o' << 56 | (long)'m' << 48 | (long)'i' << 40 | (long)'c' << 32 | (long)'r' << 24 | (long)'o' << 16 | (long)'n' << 8,
1015 (long)'o' << 56 | (long)'p' << 48 | (long)'l' << 40 | (long)'u' << 32 | (long)'s' << 24,
1016 (long)'o' << 56 | (long)'r' << 48,
1017 (long)'o' << 56 | (long)'r' << 48 | (long)'d' << 40 | (long)'f' << 32,
1018 (long)'o' << 56 | (long)'r' << 48 | (long)'d' << 40 | (long)'m' << 32,
1019 (long)'o' << 56 | (long)'s' << 48 | (long)'l' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'h' << 16,
1020 (long)'o' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
1021 (long)'o' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24 | (long)'s' << 16,
1022 (long)'o' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
1023 (long)'p' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'a' << 32,
1024 (long)'p' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'t' << 32,
1025 (long)'p' << 56 | (long)'e' << 48 | (long)'r' << 40 | (long)'m' << 32 | (long)'i' << 24 | (long)'l' << 16,
1026 (long)'p' << 56 | (long)'e' << 48 | (long)'r' << 40 | (long)'p' << 32,
1027 (long)'p' << 56 | (long)'h' << 48 | (long)'i' << 40,
1028 (long)'p' << 56 | (long)'i' << 48,
1029 (long)'p' << 56 | (long)'i' << 48 | (long)'v' << 40,
1030 (long)'p' << 56 | (long)'l' << 48 | (long)'u' << 40 | (long)'s' << 32 | (long)'m' << 24 | (long)'n' << 16,
1031 (long)'p' << 56 | (long)'o' << 48 | (long)'u' << 40 | (long)'n' << 32 | (long)'d' << 24,
1032 (long)'p' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24,
1033 (long)'p' << 56 | (long)'r' << 48 | (long)'o' << 40 | (long)'d' << 32,
1034 (long)'p' << 56 | (long)'r' << 48 | (long)'o' << 40 | (long)'p' << 32,
1035 (long)'p' << 56 | (long)'s' << 48 | (long)'i' << 40,
1036 (long)'q' << 56 | (long)'u' << 48 | (long)'o' << 40 | (long)'t' << 32,
1037 (long)'r' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
1038 (long)'r' << 56 | (long)'a' << 48 | (long)'d' << 40 | (long)'i' << 32 | (long)'c' << 24,
1039 (long)'r' << 56 | (long)'a' << 48 | (long)'n' << 40 | (long)'g' << 32,
1040 (long)'r' << 56 | (long)'a' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
1041 (long)'r' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
1042 (long)'r' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'i' << 32 | (long)'l' << 24,
1043 (long)'r' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
1044 (long)'r' << 56 | (long)'e' << 48 | (long)'a' << 40 | (long)'l' << 32,
1045 (long)'r' << 56 | (long)'e' << 48 | (long)'g' << 40,
1046 (long)'r' << 56 | (long)'f' << 48 | (long)'l' << 40 | (long)'o' << 32 | (long)'o' << 24 | (long)'r' << 16,
1047 (long)'r' << 56 | (long)'h' << 48 | (long)'o' << 40,
1048 (long)'r' << 56 | (long)'l' << 48 | (long)'m' << 40,
1049 (long)'r' << 56 | (long)'s' << 48 | (long)'a' << 40 | (long)'q' << 32 | (long)'u' << 24 | (long)'o' << 16,
1050 (long)'r' << 56 | (long)'s' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
1051 (long)'s' << 56 | (long)'b' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
1052 (long)'s' << 56 | (long)'c' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'o' << 24 | (long)'n' << 16,
1053 (long)'s' << 56 | (long)'d' << 48 | (long)'o' << 40 | (long)'t' << 32,
1054 (long)'s' << 56 | (long)'e' << 48 | (long)'c' << 40 | (long)'t' << 32,
1055 (long)'s' << 56 | (long)'h' << 48 | (long)'y' << 40,
1056 (long)'s' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24,
1057 (long)'s' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24 | (long)'f' << 16,
1058 (long)'s' << 56 | (long)'i' << 48 | (long)'m' << 40,
1059 (long)'s' << 56 | (long)'p' << 48 | (long)'a' << 40 | (long)'d' << 32 | (long)'e' << 24 | (long)'s' << 16,
1060 (long)'s' << 56 | (long)'u' << 48 | (long)'b' << 40,
1061 (long)'s' << 56 | (long)'u' << 48 | (long)'b' << 40 | (long)'e' << 32,
1062 (long)'s' << 56 | (long)'u' << 48 | (long)'m' << 40,
1063 (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40,
1064 (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'1' << 32,
1065 (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'2' << 32,
1066 (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'3' << 32,
1067 (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'e' << 32,
1068 (long)'s' << 56 | (long)'z' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
1069 (long)'t' << 56 | (long)'a' << 48 | (long)'u' << 40,
1070 (long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'r' << 32 | (long)'e' << 24 | (long)'4' << 16,
1071 (long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24,
1072 (long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24 | (long)'s' << 16 | (long)'y' << 8 | (long)'m' << 0,
1073 (long)'t' << 56 | (long)'h' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'s' << 24 | (long)'p' << 16,
1074 (long)'t' << 56 | (long)'h' << 48 | (long)'o' << 40 | (long)'r' << 32 | (long)'n' << 24,
1075 (long)'t' << 56 | (long)'i' << 48 | (long)'l' << 40 | (long)'d' << 32 | (long)'e' << 24,
1076 (long)'t' << 56 | (long)'i' << 48 | (long)'m' << 40 | (long)'e' << 32 | (long)'s' << 24,
1077 (long)'t' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'d' << 32 | (long)'e' << 24,
1078 (long)'u' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
1079 (long)'u' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
1080 (long)'u' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
1081 (long)'u' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
1082 (long)'u' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
1083 (long)'u' << 56 | (long)'m' << 48 | (long)'l' << 40,
1084 (long)'u' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'h' << 24,
1085 (long)'u' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
1086 (long)'u' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
1087 (long)'w' << 56 | (long)'e' << 48 | (long)'i' << 40 | (long)'e' << 32 | (long)'r' << 24 | (long)'p' << 16,
1088 (long)'x' << 56 | (long)'i' << 48,
1089 (long)'y' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
1090 (long)'y' << 56 | (long)'e' << 48 | (long)'n' << 40,
1091 (long)'y' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
1092 (long)'z' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
1093 (long)'z' << 56 | (long)'w' << 48 | (long)'j' << 40,
1094 (long)'z' << 56 | (long)'w' << 48 | (long)'n' << 40 | (long)'j' << 32
1097 static readonly char[] entities_values = new char[] {
1353 // The list is from http://www.w3.org/TR/REC-html40/sgml/entities.html, except for ', which
1354 // is defined in http://www.w3.org/TR/2008/REC-xml-20081126/#sec-predefined-ent.
1356 private static String[] _entitiesList = new String[] {
1612 private static Dictionary<string, char> _lookupTable = GenerateLookupTable();
1614 private static Dictionary<string, char> GenerateLookupTable() {
1615 // e[0] is unicode char, e[1] is '-', e[2+] is entity string
1617 Dictionary<string, char> lookupTable = new Dictionary<string, char>(StringComparer.Ordinal);
1618 foreach (string e in _entitiesList) {
1619 lookupTable.Add(e.Substring(2), e[0]);
1625 public static char Lookup(string entity) {
1627 _lookupTable.TryGetValue(entity, out theChar);