The Labs \ Source Viewer \ SSCLI \ System.Xml \ XmlCharType

  1. #if XMLCHARTYPE_GEN_RESOURCE
  2. #undef XMLCHARTYPE_USE_RESOURCE
  3. #endif
  4. //------------------------------------------------------------------------------
  5. // <copyright file="XmlCharType.cs" company="Microsoft">
  6. //
  7. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  8. //
  9. // The use and distribution terms for this software are contained in the file
  10. // named license.txt, which can be found in the root of this distribution.
  11. // By using this software in any fashion, you are agreeing to be bound by the
  12. // terms of this license.
  13. //
  14. // You must not remove this notice, or any other, from this software.
  15. //
  16. // </copyright>
  17. //------------------------------------------------------------------------------
  18. //#define XMLCHARTYPE_USE_RESOURCE // load the character properties from resources (XmlCharType.bin must be linked to System.Xml.dll)
  19. //#define XMLCHARTYPE_GEN_RESOURCE // generate the character properties into XmlCharType.bin
  20. #if XMLCHARTYPE_GEN_RESOURCE || XMLCHARTYPE_USE_RESOURCE
  21. using System.IO;
  22. using System.Reflection;
  23. #endif
  24. using System.Threading;
  25. using System.Diagnostics;
  26. namespace System.Xml
  27. {
  28.    
  29.     /// <include file='doc\XmlCharType.uex' path='docs/doc[@for="XmlCharType"]/*' />
  30.     /// <internalonly/>
  31.     /// <devdoc>
  32.     /// The XmlCharType class is used for quick character type recognition
  33.     /// which is optimized for the first 127 ascii characters.
  34.     /// </devdoc>
  35.     #if XMLCHARTYPE_USE_RESOURCE
  36.     unsafe internal struct XmlCharType
  37.     {
  38.         #else
  39.         internal struct XmlCharType
  40.         {
  41.             #endif
  42.             // Whitespace chars -- Section 2.3 [3]
  43.             // Letters -- Appendix B [84]
  44.             // Starting NCName characters -- Section 2.3 [5] (Starting Name characters without ':')
  45.             // NCName characters -- Section 2.3 [4] (Name characters without ':')
  46.             // Character data characters -- Section 2.2 [2]
  47.             // PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] Section 2.3 of spec
  48.             internal const int fWhitespace = 1;
  49.             internal const int fLetter = 2;
  50.             internal const int fNCStartName = 4;
  51.             internal const int fNCName = 8;
  52.             internal const int fCharData = 16;
  53.             internal const int fPublicId = 32;
  54.             internal const int fText = 64;
  55.             internal const int fAttrValue = 128;
  56.            
  57.             private const uint CharPropertiesSize = (uint)char.MaxValue + 1;
  58.            
  59.             #if !XMLCHARTYPE_USE_RESOURCE || XMLCHARTYPE_GEN_RESOURCE
  60.             internal const string s_Whitespace = "\t\n\r\r ";
  61.            
  62.             const string s_Letter = "AZazÀÖØö" + "øıĴľŁňŊž" + "ƀǃǍǰǴǵǺȗ" + "ɐʨʻˁΆΆΈΊ" + "ΌΌΎΡΣώϐϖ" + "ϚϚϜϜϞϞϠϠ" + "ϢϳЁЌЎяёќ" + "ўҁҐӄӇӈӋӌ" + "ӐӫӮӵӸӹԱՖ" + "ՙՙաֆאתװײ" + "ءغفيٱڷںھ" + "ۀێېۓەەۥۦ" + "अहऽऽक़ॡঅঌ" + "এঐওনপরলল" + "শহড়ঢ়য়ৡৰৱ" + "ਅਊਏਐਓਨਪਰ" + "ਲਲ਼ਵਸ਼ਸਹਖ਼ੜ" + "ਫ਼ਫ਼ੲੴઅઋઍઍ" + "એઑઓનપરલળ" + "વહઽઽૠૠଅଌ" + "ଏଐଓନପରଲଳ" + "ଶହଽଽଡ଼ଢ଼ୟୡ" + "அஊஎஐஒகஙச" + "ஜஜஞடணதநப" + "மவஷஹఅఌఎఐ" + "ఒనపళవహౠౡ" + "ಅಌಎಐಒನಪಳ" + "ವಹೞೞೠೡഅഌ" + "എഐഒനപഹൠൡ" + "กฮะะาำเๅ" + "ກຂຄຄງຈຊຊ" + "ຍຍດທນຟມຣ" + "ລລວວສຫອຮ" + "ະະາຳຽຽເໄ" + "ཀཇཉཀྵႠჅაჶ" + "ᄀᄀᄂᄃᄅᄇᄉᄉ" + "ᄋᄌᄎᄒᄼᄼᄾᄾ" + "ᅀᅀᅌᅌᅎᅎᅐᅐ" + "ᅔᅕᅙᅙᅟᅡᅣᅣ" + "ᅥᅥᅧᅧᅩᅩᅭᅮ" + "ᅲᅳᅵᅵᆞᆞᆨᆨ" + "ᆫᆫᆮᆯᆷᆸᆺᆺ" + "ᆼᇂᇫᇫᇰᇰᇹᇹ" + "ḀẛẠỹἀἕἘἝ" + "ἠὅὈὍὐὗὙὙ" + "ὛὛὝὝὟώᾀᾴ" + "ᾶᾼιιῂῄῆῌ" + "ῐΐῖΊῠῬῲῴ" + "ῶῼΩΩKÅ℮℮" + "ↀↂ〇〇〡〩ぁゔ" + "ァヺㄅㄬ一龥가힣";
  63.            
  64.             const string s_NCStartName = "AZ__az" + "ÀÖØöøıĴľ" + "ŁňŊžƀǃǍǰ" + "ǴǵǺȗɐʨʻˁ" + "ΆΆΈΊΌΌΎΡ" + "ΣώϐϖϚϚϜϜ" + "ϞϞϠϠϢϳЁЌ" + "ЎяёќўҁҐӄ" + "ӇӈӋӌӐӫӮӵ" + "ӸӹԱՖՙՙաֆ" + "אתװײءغفي" + "ٱڷںھۀێېۓ" + "ەەۥۦअहऽऽ" + "क़ॡঅঌএঐওন" + "পরললশহড়ঢ়" + "য়ৡৰৱਅਊਏਐ" + "ਓਨਪਰਲਲ਼ਵਸ਼" + "ਸਹਖ਼ੜਫ਼ਫ਼ੲੴ" + "અઋઍઍએઑઓન" + "પરલળવહઽઽ" + "ૠૠଅଌଏଐଓନ" + "ପରଲଳଶହଽଽ" + "ଡ଼ଢ଼ୟୡஅஊஎஐ" + "ஒகஙசஜஜஞட" + "ணதநபமவஷஹ" + "అఌఎఐఒనపళ" + "వహౠౡಅಌಎಐ" + "ಒನಪಳವಹೞೞ" + "ೠೡഅഌഎഐഒന" + "പഹൠൡกฮะะ" + "าำเๅກຂຄຄ" + "ງຈຊຊຍຍດທ" + "ນຟມຣລລວວ" + "ສຫອຮະະາຳ" + "ຽຽເໄཀཇཉཀྵ" + "ႠჅაჶᄀᄀᄂᄃ" + "ᄅᄇᄉᄉᄋᄌᄎᄒ" + "ᄼᄼᄾᄾᅀᅀᅌᅌ" + "ᅎᅎᅐᅐᅔᅕᅙᅙ" + "ᅟᅡᅣᅣᅥᅥᅧᅧ" + "ᅩᅩᅭᅮᅲᅳᅵᅵ" + "ᆞᆞᆨᆨᆫᆫᆮᆯ" + "ᆷᆸᆺᆺᆼᇂᇫᇫ" + "ᇰᇰᇹᇹḀẛẠỹ" + "ἀἕἘἝἠὅὈὍ" + "ὐὗὙὙὛὛὝὝ" + "Ὗώᾀᾴᾶᾼιι" + "ῂῄῆῌῐΐῖΊ" + "ῠῬῲῴῶῼΩΩ" + "KÅ℮℮ↀↂ〇〇" + "〡〩ぁゔァヺㄅㄬ" + "一龥가힣";
  65.            
  66.             const string s_NCName = "-.09AZ__" + "az··ÀÖØö" + "øıĴľŁňŊž" + "ƀǃǍǰǴǵǺȗ" + "ɐʨʻˁːˑ̀ͅ" + "͠͡ΆΊΌΌΎΡ" + "ΣώϐϖϚϚϜϜ" + "ϞϞϠϠϢϳЁЌ" + "Ўяёќўҁ҃҆" + "ҐӄӇӈӋӌӐӫ" + "ӮӵӸӹԱՖՙՙ" + "աֆֹֻֽ֑֣֡" + "ֿֿׁׂׄׄאת" + "װײءغـْ٠٩" + "ٰڷںھۀێېۓ" + "ە۪ۭۨ۰۹ँः" + "अह़्॑॔क़ॣ" + "०९ঁঃঅঌএঐ" + "ওনপরললশহ" + "়়াৄেৈো্" + "ৗৗড়ঢ়য়ৣ০ৱ" + "ਂਂਅਊਏਐਓਨ" + "ਪਰਲਲ਼ਵਸ਼ਸਹ" + "਼਼ਾੂੇੈੋ੍" + "ਖ਼ੜਫ਼ਫ਼੦ੴઁઃ" + "અઋઍઍએઑઓન" + "પરલળવહ઼ૅ" + "ેૉો્ૠૠ૦૯" + "ଁଃଅଌଏଐଓନ" + "ପରଲଳଶହ଼ୃ" + "େୈୋ୍ୖୗଡ଼ଢ଼" + "ୟୡ୦୯ஂஃஅஊ" + "எஐஒகஙசஜஜ" + "ஞடணதநபமவ" + "ஷஹாூெைொ்" + "ௗௗ௧௯ఁఃఅఌ" + "ఎఐఒనపళవహ" + "ాౄెైొ్ౕౖ" + "ౠౡ౦౯ಂಃಅಌ" + "ಎಐಒನಪಳವಹ" + "ಾೄೆೈೊ್ೕೖ" + "ೞೞೠೡ೦೯ംഃ" + "അഌഎഐഒനപഹ" + "ാൃെൈൊ്ൗൗ" + "ൠൡ൦൯กฮะฺ" + "เ๎๐๙ກຂຄຄ" + "ງຈຊຊຍຍດທ" + "ນຟມຣລລວວ" + "ສຫອຮະູົຽ" + "ເໄໆໆ່ໍ໐໙" + "༘༙༠༩༵༵༷༷" + "༹༹༾ཇཉཀྵ྄ཱ" + "྆ྋྐྕྗྗྙྭ" + "ྱྷྐྵྐྵႠჅაჶ" + "ᄀᄀᄂᄃᄅᄇᄉᄉ" + "ᄋᄌᄎᄒᄼᄼᄾᄾ" + "ᅀᅀᅌᅌᅎᅎᅐᅐ" + "ᅔᅕᅙᅙᅟᅡᅣᅣ" + "ᅥᅥᅧᅧᅩᅩᅭᅮ" + "ᅲᅳᅵᅵᆞᆞᆨᆨ" + "ᆫᆫᆮᆯᆷᆸᆺᆺ" + "ᆼᇂᇫᇫᇰᇰᇹᇹ" + "ḀẛẠỹἀἕἘἝ" + "ἠὅὈὍὐὗὙὙ" + "ὛὛὝὝὟώᾀᾴ" + "ᾶᾼιιῂῄῆῌ" + "ῐΐῖΊῠῬῲῴ" + "ῶῼ⃐⃜⃡⃡ΩΩ" + "KÅ℮℮ↀↂ々々" + "〇〇〡〯〱〵ぁゔ" + "゙゚ゝゞァヺーヾ" + "ㄅㄬ一龥가힣";
  67.            
  68.             const string s_CharData = "\t\n\r\r ퟿�";
  69.            
  70.             const string s_PublicID = "\n\n\r\r !#%" + "';==?Z__" + "az";
  71.            
  72.                 // TextChar = CharData - { 0xA | 0xD | '<' | '&' | 0x9 | ']' | 0xDC00 - 0xDFFF }
  73.             const string s_Text = " %';=\\^퟿�";
  74.            
  75.                 // AttrValueChar = CharData - { 0xA | 0xD | 0x9 | '<' | '>' | '&' | '\'' | '"' | 0xDC00 - 0xDFFF }
  76.             const string s_AttrValue = " !#%(;==?퟿�";
  77.             #endif
  78.            
  79.             // static lock for XmlCharType class
  80.             private static object s_Lock;
  81.            
  82.             private static object StaticLock {
  83.                 get {
  84.                     if (s_Lock == null) {
  85.                         object o = new object();
  86.                         Interlocked.CompareExchange(ref s_Lock, o, null);
  87.                     }
  88.                     return s_Lock;
  89.                 }
  90.             }
  91.            
  92.             #if XMLCHARTYPE_USE_RESOURCE
  93.             private static byte* s_CharProperties;
  94.             internal byte* charProperties;
  95.            
  96.             static void InitInstance()
  97.             {
  98.                 lock (StaticLock) {
  99.                     if (s_CharProperties != null) {
  100.                         return;
  101.                     }
  102.                    
  103.                     UnmanagedMemoryStream memStream = (UnmanagedMemoryStream)Assembly.GetExecutingAssembly().GetManifestResourceStream("XmlCharType.bin");
  104.                     Debug.Assert(memStream.Length == CharPropertiesSize);
  105.                    
  106.                     byte* chProps = memStream.PositionPointer;
  107.                     Thread.MemoryBarrier();
  108.                     // For weak memory models (IA64)
  109.                     s_CharProperties = chProps;
  110.                 }
  111.             }
  112.            
  113.             #else // !XMLCHARTYPE_USE_RESOURCE
  114.             private static byte[] s_CharProperties;
  115.             internal byte[] charProperties;
  116.            
  117.             static void InitInstance()
  118.             {
  119.                 lock (StaticLock) {
  120.                     if (s_CharProperties != null) {
  121.                         return;
  122.                     }
  123.                    
  124.                     byte[] chProps = new byte[CharPropertiesSize];
  125.                     Thread.MemoryBarrier();
  126.                     // For weak memory models (IA64)
  127.                     s_CharProperties = chProps;
  128.                    
  129.                     SetProperties(s_Whitespace, fWhitespace);
  130.                     SetProperties(s_Letter, fLetter);
  131.                     SetProperties(s_NCStartName, fNCStartName);
  132.                     SetProperties(s_NCName, fNCName);
  133.                     SetProperties(s_CharData, fCharData);
  134.                     SetProperties(s_PublicID, fPublicId);
  135.                     SetProperties(s_Text, fText);
  136.                     SetProperties(s_AttrValue, fAttrValue);
  137.                 }
  138.             }
  139.            
  140.             private static void SetProperties(string ranges, byte value)
  141.             {
  142.                 for (int p = 0; p < ranges.Length; p += 2) {
  143.                     for (int i = ranges[p]int last = ranges[p + 1]; i <= last; i++) {
  144.                         s_CharProperties[i] |= value;
  145.                     }
  146.                 }
  147.             }
  148.             #endif
  149.            
  150.             #if XMLCHARTYPE_USE_RESOURCE
  151.             private XmlCharType(byte* charProperties)
  152.             {
  153.             }
  154.             #else
  155.             private XmlCharType(byte[] charProperties)
  156.             {
  157.                 #endif
  158.                 Debug.Assert(s_CharProperties != null);
  159.                 this.charProperties = charProperties;
  160.             }
  161.            
  162.             static internal XmlCharType Instance {
  163.                 get {
  164.                     if (s_CharProperties == null) {
  165.                         InitInstance();
  166.                     }
  167.                     return new XmlCharType(s_CharProperties);
  168.                 }
  169.             }
  170.            
  171.             // NOTE: This method will not be inlined (because it uses byte* charProperties)
  172.             public bool IsWhiteSpace(char ch)
  173.             {
  174.                 return (charProperties[ch] & fWhitespace) != 0;
  175.             }
  176.            
  177.             // NOTE: This method will not be inlined (because it uses byte* charProperties)
  178.             public bool IsLetter(char ch)
  179.             {
  180.                 return (charProperties[ch] & fLetter) != 0;
  181.             }
  182.            
  183.             public bool IsExtender(char ch)
  184.             {
  185.                 return (ch == 183);
  186.             }
  187.            
  188.             /// NOTE: This method will not be inlined (because it uses byte* charProperties)
  189.             public bool IsNCNameChar(char ch)
  190.             {
  191.                 return (charProperties[ch] & fNCName) != 0;
  192.             }
  193.            
  194.             // NOTE: This method will not be inlined (because it uses byte* charProperties)
  195.             public bool IsStartNCNameChar(char ch)
  196.             {
  197.                 return (charProperties[ch] & fNCStartName) != 0;
  198.             }
  199.            
  200.             // NOTE: This method will not be inlined (because it uses byte* charProperties)
  201.             public bool IsCharData(char ch)
  202.             {
  203.                 return (charProperties[ch] & fCharData) != 0;
  204.             }
  205.            
  206.             // [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] Section 2.3 of spec
  207.             // NOTE: This method will not be inlined (because it uses byte* charProperties)
  208.             public bool IsPubidChar(char ch)
  209.             {
  210.                 return (charProperties[ch] & fPublicId) != 0;
  211.             }
  212.            
  213.             // TextChar = CharData - { 0xA, 0xD, '<', '&', ']' }
  214.             // NOTE: This method will not be inlined (because it uses byte* charProperties)
  215.             internal bool IsTextChar(char ch)
  216.             {
  217.                 return (charProperties[ch] & fText) != 0;
  218.             }
  219.            
  220.             // AttrValueChar = CharData - { 0xA, 0xD, 0x9, '<', '>', '&', '\'', '"' }
  221.             // NOTE: This method will not be inlined (because it uses byte* charProperties)
  222.             internal bool IsAttributeValueChar(char ch)
  223.             {
  224.                 return (charProperties[ch] & fAttrValue) != 0;
  225.             }
  226.            
  227.             public bool IsNameChar(char ch)
  228.             {
  229.                 return IsNCNameChar(ch) || ch == ':';
  230.             }
  231.            
  232.             public bool IsStartNameChar(char ch)
  233.             {
  234.                 return IsStartNCNameChar(ch) || ch == ':';
  235.             }
  236.            
  237.             public bool IsDigit(char ch)
  238.             {
  239.                 return (ch >= 48 && ch <= 57);
  240.             }
  241.            
  242.             public bool IsHexDigit(char ch)
  243.             {
  244.                 return (ch >= 48 && ch <= 57) || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F');
  245.             }
  246.            
  247.             internal bool IsOnlyWhitespace(string str)
  248.             {
  249.                 return IsOnlyWhitespaceWithPos(str) == -1;
  250.             }
  251.            
  252.             internal int IsOnlyWhitespaceWithPos(string str)
  253.             {
  254.                 if (str != null) {
  255.                     for (int i = 0; i < str.Length; i++) {
  256.                         if ((charProperties[str[i]] & fWhitespace) == 0) {
  257.                             return i;
  258.                         }
  259.                     }
  260.                 }
  261.                 return -1;
  262.             }
  263.            
  264.             internal bool IsName(string str)
  265.             {
  266.                 if (str.Length == 0 || !IsStartNameChar(str[0])) {
  267.                     return false;
  268.                 }
  269.                 for (int i = 1; i < str.Length; i++) {
  270.                     if (!IsNameChar(str[i])) {
  271.                         return false;
  272.                     }
  273.                 }
  274.                 return true;
  275.             }
  276.            
  277.             internal bool IsNmToken(string str)
  278.             {
  279.                 if (str.Length == 0) {
  280.                     return false;
  281.                 }
  282.                 for (int i = 0; i < str.Length; i++) {
  283.                     if ((charProperties[str[i]] & fNCName) == 0 && str[i] != ':') {
  284.                         return false;
  285.                     }
  286.                 }
  287.                 return true;
  288.             }
  289.            
  290.             internal int IsOnlyCharData(string str)
  291.             {
  292.                 if (str != null) {
  293.                     for (int i = 0; i < str.Length; i++) {
  294.                         if ((charProperties[str[i]] & fCharData) == 0) {
  295.                             return i;
  296.                         }
  297.                     }
  298.                 }
  299.                 return -1;
  300.             }
  301.            
  302.             internal int IsPublicId(string str)
  303.             {
  304.                 if (str != null) {
  305.                     for (int i = 0; i < str.Length; i++) {
  306.                         if ((charProperties[str[i]] & fPublicId) == 0) {
  307.                             return i;
  308.                         }
  309.                     }
  310.                 }
  311.                 return -1;
  312.             }
  313.            
  314.             #if XMLCHARTYPE_GEN_RESOURCE
  315.             public static void Main(string[] args)
  316.             {
  317.                 try {
  318.                     InitInstance();
  319.                    
  320.                     string fileName = (args.Length == 0) ? "XmlCharType.bin" : args[0];
  321.                     Console.Write("Writing XmlCharType character properties to {0}...", fileName);
  322.                    
  323.                     FileStream fs = new FileStream(fileName, FileMode.Create);
  324.                     for (int i = 0; i < CharPropertiesSize; i += 4096) {
  325.                         fs.Write(s_CharProperties, i, 4096);
  326.                     }
  327.                     fs.Close();
  328.                     Console.WriteLine("done.");
  329.                 }
  330.                 catch (Exception e) {
  331.                     Console.WriteLine();
  332.                     Console.WriteLine("Exception: {0}", e.Message);
  333.                 }
  334.             }
  335.             #endif
  336.         }
  337.     }
  338. }

Developer Fusion