xmlvalid.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:24k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: xmlvalid.cpp,v 1.4.32.3 2004/07/09 01:44:10 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hxtypes.h"
  50. #include "hxcom.h"
  51. #include "hxassert.h"
  52. #ifdef XXXJHUG
  53. #include "hlxclib/stdio.h"
  54. #endif /* XXXJHUG */
  55. #include "hlxclib/stdlib.h"
  56. #include "xmlvalid.h"
  57. #include "hlxclib/string.h"
  58. BOOL ISO8859Valid::IsNameValid(const BYTE* p, UINT32 len)
  59. {
  60.     BOOL bValid = IsLetter(*p) || IsDigit(*p) || *p == '_' || *p == ':';
  61.     for (const BYTE* end = p + len; bValid && *p && p < end; ++p )
  62.     {
  63. bValid = IsLetter(*p) || IsDigit(*p) || *p == '.' ||
  64.     *p == '-' || *p == '_' || *p == ':' || 
  65.     IsCombiningChar(*p);
  66.     }
  67.     return bValid;
  68. }
  69. BOOL ISO8859Valid::IsNmtokenValid(const BYTE* p, UINT32 len)
  70. {
  71.     BOOL bValid = TRUE;
  72.     
  73.     for (const BYTE* end = p + len; bValid && *p && p < end; ++p )
  74.     {
  75. bValid = IsLetter(*p) || IsDigit(*p) || *p == '.' ||
  76.     *p == '-' || *p == '_' || *p == ':' || 
  77.     IsCombiningChar(*p);
  78.     }
  79.     return bValid;
  80. }
  81. // assume that string has allready been parsed for ' and "
  82. //::=  '"' ([^%&"] | PEReference | Reference)* '"'  
  83. //   |  "'" ([^%&'] | PEReference | Reference)* "'" 
  84. BOOL ISO8859Valid::IsEntityValueValid(const BYTE* p, UINT32 len)
  85. {
  86.     BOOL bValid = TRUE;
  87.     const BYTE* pBeginRef = NULL;
  88.     
  89.     for (const BYTE* end = p + len; bValid && *p && p < end; ++p )
  90.     {
  91. if ( *p == '&' || *p == '%' )
  92. {
  93.     pBeginRef = p;
  94. }
  95. else if (pBeginRef && *p == ';')
  96. {
  97.     bValid = IsRefValid(pBeginRef + 1, p - pBeginRef - 1);
  98.     pBeginRef = NULL;
  99. }
  100.     }
  101.     return bValid;
  102. }
  103. BOOL ISO8859Valid::IsRefValid(const BYTE *p, UINT32 len)
  104. {
  105.     BOOL bValid = FALSE;
  106.     HX_ASSERT(*(p -1) == '&');
  107.     // ref - 0 - nothing, '&' - beginning of Refference
  108.     //      'n' - beginning of number
  109.     //      'h' - hex number
  110.     //      'd' - decimal number
  111.     //      'e' - entity reference
  112.     BYTE ref = '&';
  113.     const BYTE* pBeginRef = NULL;
  114.     
  115.     for (const BYTE* end = p + len; bValid && *p && p < end; ++p )
  116.     {
  117. switch ( ref )
  118. {
  119. case '&':
  120.     if ( *p == '#' )
  121.     {
  122. ref = 'n';
  123.     }
  124.     else
  125.     {
  126. ref = 'e';
  127. pBeginRef = p;
  128.     }
  129.     break;
  130. case 'n':
  131.     if (*p == 'x' || *p == 'X')
  132.     {
  133. ref = 'h';
  134.     }
  135.     else
  136.     {
  137. ref = 'd';
  138. bValid = IsDigit(*p);
  139.     }
  140.     break;
  141. case 'd':
  142.     if ( *p == ';' )
  143.     {
  144. ref = '';
  145.     }
  146.     else 
  147.     {
  148. bValid = IsDigit(*p);
  149.     }
  150.     break;
  151. case 'h':
  152.     if ( *p == ';' )
  153.     {
  154. ref = '';
  155.     }
  156.     else
  157.     {
  158. bValid = IsDigit(*p) || BETWEEN(*p, 'a', 'f') 
  159.     || BETWEEN(*p, 'A', 'F');
  160.     }
  161.     break;
  162. case 'e':
  163.     if ( *p == ';' )
  164.     {
  165. // this could be checked as we go in a single pass.
  166. bValid = IsNameValid(pBeginRef, p - pBeginRef);
  167. pBeginRef = NULL;
  168. ref = '';
  169.     }
  170.     break;
  171. case '':
  172.     return bValid;
  173. }
  174.     }
  175.     return bValid;
  176. }
  177. // assume that string has allready been parsed for ' and "
  178. // AttValue ::=  '"' ([^<&"] | Reference)* '"'  
  179. //   |  "'" ([^<&'] | Reference)* "'" 
  180. BOOL ISO8859Valid::IsAttValueValid(const BYTE* p, UINT32 len)
  181. {
  182.     BOOL bValid = TRUE;
  183.     const BYTE* pBeginRef = NULL;
  184.     
  185.     for (const BYTE* end = p + len; bValid && *p && p < end; ++p )
  186.     {
  187. if ( *p == '&' )
  188. {
  189.     bValid = FALSE;
  190.     pBeginRef = p;
  191. }
  192. else if (*p == '<')
  193. {
  194.     bValid = FALSE;
  195. }
  196. else if (pBeginRef && *p == ';')
  197. {
  198.     bValid = IsRefValid(pBeginRef + 1, p - pBeginRef - 1);
  199.     pBeginRef = NULL;
  200. }
  201.     }
  202.     return bValid;
  203. }
  204. //SystemLiteral ::=  ('"' [^"]* '"') | ("'" [^']* "'")  
  205. // assuming that the deliminators have allready been parsed.
  206. // there fore system literals should allways be valid.
  207. BOOL ISO8859Valid::IsSystemLiteralValid(const BYTE* p, UINT32 len)
  208. {
  209.     return TRUE;
  210. }
  211. // Public ID Literal
  212. //[12]  PubidLiteral ::=  '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" 
  213. //[13]  PubidChar ::=  #x20 | #xD | #xA | [a-zA-Z0-9] | [] 
  214. BOOL ISO8859Valid::IsPubidLiteralValid(const BYTE* p, UINT32 len)
  215. {
  216.     BOOL bValid = TRUE;
  217.     for (const BYTE* end = p + len; bValid && *p && p < end; ++p )
  218.     {
  219. bValid = *p == 0x20 || *p == 0xD || *p == 0xA || BETWEEN(*p, 'a', 'z') || 
  220.     BETWEEN(*p, 'A', 'Z') || BETWEEN(*p, '0', '9') || strchr("-()+,./:=?;!*#@$_%", *p);
  221.     }
  222.     return bValid;
  223. }
  224. inline BOOL ISO8859Valid::IsLetter(const BYTE c)
  225. {
  226.     return IsBaseChar(c) || IsIdeographic(c);
  227. }
  228. inline BOOL ISO8859Valid::IsBaseChar(const BYTE c)
  229. {
  230.     return BETWEEN(c, 0x41, 0x5A) || BETWEEN(c, 0x61, 0x7A) || 
  231.    BETWEEN(c, 0xC0, 0xD6) || BETWEEN(c, 0xD8, 0xF6) ||
  232.    BETWEEN(c, 0xF8, 0xFF);
  233. }
  234. inline BOOL ISO8859Valid::IsIdeographic(const BYTE c)
  235. {
  236.     return FALSE;
  237. }
  238. inline BOOL ISO8859Valid::IsCombiningChar(const BYTE c)
  239. {
  240.     return FALSE;
  241. }
  242. inline BOOL ISO8859Valid::IsDigit(const BYTE c)
  243. {
  244.     return BETWEEN(c, 0x30, 0x39);
  245. }
  246. inline BOOL ISO8859Valid::IsExtender(const BYTE c)
  247. {
  248.     return c == 0xB7;
  249. }
  250. BOOL UTF16Valid::IsNameValid(const UINT16* p, UINT32 len)
  251. {
  252.     BOOL bValid = IsLetter(*p) || IsDigit(*p) || *p == '_' || *p == ':';
  253.     for (const UINT16* end = p + len; bValid && *p && p < end; ++p )
  254.     {
  255. bValid = IsLetter(*p) || IsDigit(*p) || *p == '.' ||
  256.     *p == '-' || *p == '_' || *p == ':' || 
  257.     IsCombiningChar(*p);
  258.     }
  259.     return bValid;
  260. }
  261. BOOL UTF16Valid::IsNmtokenValid(const UINT16* p, UINT32 len)
  262. {
  263.     BOOL bValid = TRUE;
  264.     
  265.     for (const UINT16* end = p + len; bValid && *p && p < end; ++p )
  266.     {
  267. bValid = IsLetter(*p) || IsDigit(*p) || *p == '.' ||
  268.     *p == '-' || *p == '_' || *p == ':' || 
  269.     IsCombiningChar(*p);
  270.     }
  271.     return bValid;
  272. }
  273. // these four functions assume that the ' or " deliminators have
  274. // allready been parsed.
  275. BOOL UTF16Valid::IsEntityValueValid(const UINT16* p, UINT32 len)
  276. {
  277.     // copy UTF8 after it has been tested.
  278.     return FALSE;
  279. }
  280. BOOL UTF16Valid::IsAttValueValid(const UINT16* p, UINT32 len)
  281. {
  282.     // copy UTF8 after it has been tested.
  283.     return FALSE;
  284. }
  285. BOOL UTF16Valid::IsSystemLiteralValid(const UINT16* p, UINT32 len)
  286. {
  287.     return TRUE;
  288. }
  289. BOOL UTF16Valid::IsPubidLiteralValid(const UINT16* p, UINT32 len)
  290. {
  291.     BOOL bValid = TRUE;
  292.     for (const UINT16* end = p + len; bValid && *p && p < end; ++p )
  293.     {
  294. bValid = *p == 0x20 || *p == 0xD || *p == 0xA || BETWEEN(*p, 'a', 'z') || 
  295.     BETWEEN(*p, 'A', 'Z') || BETWEEN(*p, '0', '9') || strchr("-()+,./:=?;!*#@$_%", *p);
  296.     }
  297.     return bValid;
  298. }
  299. struct Node
  300. {
  301.     UINT16 Begin;
  302.     UINT16 End;
  303. };
  304. static const Node pBaseChar[] = {
  305.         { 0x0041, 0x005A }, { 0x0061, 0x007A }, { 0x00C0, 0x00D6 }, { 0x00D8, 0x00F6 },
  306.         { 0x00F8, 0x00FF }, { 0x0100, 0x0131 }, { 0x0134, 0x013E }, { 0x0141, 0x0148 },
  307.         { 0x014A, 0x017E }, { 0x0180, 0x01C3 }, { 0x01CD, 0x01F0 }, { 0x01F4, 0x01F5 },
  308.         { 0x01FA, 0x0217 }, { 0x0250, 0x02A8 }, { 0x02BB, 0x02C1 }, { 0x0386, 0x0386 },
  309.         { 0x0388, 0x038A }, { 0x038C, 0x038C }, { 0x038E, 0x03A1 }, { 0x03A3, 0x03CE },
  310.         { 0x03D0, 0x03D6 }, { 0x03DA, 0x03DA }, { 0x03DC, 0x03DC }, { 0x03DE, 0x03DE },
  311.         { 0x03E0, 0x03E0 }, { 0x03E2, 0x03F3 }, { 0x0401, 0x040C }, { 0x040E, 0x044F },
  312.         { 0x0451, 0x045C }, { 0x045E, 0x0481 }, { 0x0490, 0x04C4 }, { 0x04C7, 0x04C8 },
  313.         { 0x04CB, 0x04CC }, { 0x04D0, 0x04EB }, { 0x04EE, 0x04F5 }, { 0x04F8, 0x04F9 },
  314.         { 0x0531, 0x0556 }, { 0x0559, 0x0559 }, { 0x0561, 0x0586 }, { 0x05D0, 0x05EA },
  315.         { 0x05F0, 0x05F2 }, { 0x0621, 0x063A }, { 0x0641, 0x064A }, { 0x0671, 0x06B7 },
  316.         { 0x06BA, 0x06BE }, { 0x06C0, 0x06CE }, { 0x06D0, 0x06D3 }, { 0x06D5, 0x06D5 },
  317.         { 0x06E5, 0x06E6 }, { 0x0905, 0x0939 }, { 0x093D, 0x093D }, { 0x0958, 0x0961 },
  318.         { 0x0985, 0x098C }, { 0x098F, 0x0990 }, { 0x0993, 0x09A8 }, { 0x09AA, 0x09B0 },
  319.         { 0x09B2, 0x09B2 }, { 0x09B6, 0x09B9 }, { 0x09DC, 0x09DD }, { 0x09DF, 0x09E1 },
  320.         { 0x09F0, 0x09F1 }, { 0x0A05, 0x0A0A }, { 0x0A0F, 0x0A10 }, { 0x0A13, 0x0A28 },
  321.         { 0x0A2A, 0x0A30 }, { 0x0A32, 0x0A33 }, { 0x0A35, 0x0A36 }, { 0x0A38, 0x0A39 },
  322.         { 0x0A59, 0x0A5C }, { 0x0A5E, 0x0A5E }, { 0x0A72, 0x0A74 }, { 0x0A85, 0x0A8B },
  323.         { 0x0A8D, 0x0A8D }, { 0x0A8F, 0x0A91 }, { 0x0A93, 0x0AA8 }, { 0x0AAA, 0x0AB0 },
  324.         { 0x0AB2, 0x0AB3 }, { 0x0AB5, 0x0AB9 }, { 0x0ABD, 0x0ABD }, { 0x0AE0, 0x0AE0 },
  325.         { 0x0B05, 0x0B0C }, { 0x0B0F, 0x0B10 }, { 0x0B13, 0x0B28 }, { 0x0B2A, 0x0B30 },
  326.         { 0x0B32, 0x0B33 }, { 0x0B36, 0x0B39 }, { 0x0B3D, 0x0B3D }, { 0x0B5C, 0x0B5D },
  327.         { 0x0B5F, 0x0B61 }, { 0x0B85, 0x0B8A }, { 0x0B8E, 0x0B90 }, { 0x0B92, 0x0B95 },
  328.         { 0x0B99, 0x0B9A }, { 0x0B9C, 0x0B9C }, { 0x0B9E, 0x0B9F }, { 0x0BA3, 0x0BA4 },
  329.         { 0x0BA8, 0x0BAA }, { 0x0BAE, 0x0BB5 }, { 0x0BB7, 0x0BB9 }, { 0x0C05, 0x0C0C },
  330.         { 0x0C0E, 0x0C10 }, { 0x0C12, 0x0C28 }, { 0x0C2A, 0x0C33 }, { 0x0C35, 0x0C39 },
  331.         { 0x0C60, 0x0C61 }, { 0x0C85, 0x0C8C }, { 0x0C8E, 0x0C90 }, { 0x0C92, 0x0CA8 },
  332.         { 0x0CAA, 0x0CB3 }, { 0x0CB5, 0x0CB9 }, { 0x0CDE, 0x0CDE }, { 0x0CE0, 0x0CE1 },
  333.         { 0x0D05, 0x0D0C }, { 0x0D0E, 0x0D10 }, { 0x0D12, 0x0D28 }, { 0x0D2A, 0x0D39 },
  334.         { 0x0D60, 0x0D61 }, { 0x0E01, 0x0E2E }, { 0x0E30, 0x0E30 }, { 0x0E32, 0x0E33 },
  335.         { 0x0E40, 0x0E45 }, { 0x0E81, 0x0E82 }, { 0x0E84, 0x0E84 }, { 0x0E87, 0x0E88 },
  336.         { 0x0E8A, 0x0E8A }, { 0x0E8D, 0x0E8D }, { 0x0E94, 0x0E97 }, { 0x0E99, 0x0E9F },
  337.         { 0x0EA1, 0x0EA3 }, { 0x0EA5, 0x0EA5 }, { 0x0EA7, 0x0EA7 }, { 0x0EAA, 0x0EAB },
  338.         { 0x0EAD, 0x0EAE }, { 0x0EB0, 0x0EB0 }, { 0x0EB2, 0x0EB3 }, { 0x0EBD, 0x0EBD },
  339.         { 0x0EC0, 0x0EC4 }, { 0x0F40, 0x0F47 }, { 0x0F49, 0x0F69 }, { 0x10A0, 0x10C5 },
  340.         { 0x10D0, 0x10F6 }, { 0x1100, 0x1100 }, { 0x1102, 0x1103 }, { 0x1105, 0x1107 },
  341.         { 0x1109, 0x1109 }, { 0x110B, 0x110C }, { 0x110E, 0x1112 }, { 0x113C, 0x113C },
  342.         { 0x113E, 0x113E }, { 0x1140, 0x1140 }, { 0x114C, 0x114C }, { 0x114E, 0x114E },
  343.         { 0x1150, 0x1150 }, { 0x1154, 0x1155 }, { 0x1159, 0x1159 }, { 0x115F, 0x1161 },
  344.         { 0x1163, 0x1163 }, { 0x1165, 0x1165 }, { 0x1167, 0x1167 }, { 0x1169, 0x1169 },
  345.         { 0x116D, 0x116E }, { 0x1172, 0x1173 }, { 0x1175, 0x1175 }, { 0x119E, 0x119E },
  346.         { 0x11A8, 0x11A8 }, { 0x11AB, 0x11AB }, { 0x11AE, 0x11AF }, { 0x11B7, 0x11B8 },
  347.         { 0x11BA, 0x11BA }, { 0x11BC, 0x11C2 }, { 0x11EB, 0x11EB }, { 0x11F0, 0x11F0 },
  348.         { 0x11F9, 0x11F9 }, { 0x1E00, 0x1E9B }, { 0x1EA0, 0x1EF9 }, { 0x1F00, 0x1F15 },
  349.         { 0x1F18, 0x1F1D }, { 0x1F20, 0x1F45 }, { 0x1F48, 0x1F4D }, { 0x1F50, 0x1F57 },
  350.         { 0x1F59, 0x1F59 }, { 0x1F5B, 0x1F5B }, { 0x1F5D, 0x1F5D }, { 0x1F5F, 0x1F7D },
  351.         { 0x1F80, 0x1FB4 }, { 0x1FB6, 0x1FBC }, { 0x1FBE, 0x1FBE }, { 0x1FC2, 0x1FC4 },
  352.         { 0x1FC6, 0x1FCC }, { 0x1FD0, 0x1FD3 }, { 0x1FD6, 0x1FDB }, { 0x1FE0, 0x1FEC },
  353.         { 0x1FF2, 0x1FF4 }, { 0x1FF6, 0x1FFC }, { 0x2126, 0x2126 }, { 0x212A, 0x212B },
  354.         { 0x212E, 0x212E }, { 0x2180, 0x2182 }, { 0x3041, 0x3094 }, { 0x30A1, 0x30FA },
  355.         { 0x3105, 0x312C }, { 0xAC00, 0xD7A3 }
  356. };
  357. int compare(const void* elem1, const void* elem2)
  358. {
  359.     if ( *((const UINT16*)elem1) < ((Node*)elem2)->Begin )
  360.     {
  361. return -1;
  362.     }
  363.     else if ( *((const UINT16*)elem1) > ((Node*)elem2)->End )
  364.     {
  365. return 1;
  366.     }
  367.     else
  368.     {
  369.  return 0;
  370.     }
  371. }
  372. inline BOOL UTF16Valid::IsLetter(const UINT16 c)
  373. {
  374.     return IsBaseChar(c) || IsIdeographic(c);
  375. }
  376. inline BOOL UTF16Valid::IsBaseChar(const UINT16 c)
  377. {
  378.     return (bsearch(&c, pBaseChar, sizeof(pBaseChar)/sizeof(Node), sizeof(Node), compare) ? TRUE : FALSE );
  379. }
  380. inline BOOL UTF16Valid::IsIdeographic(const UINT16 c)
  381. {
  382.     return BETWEEN(c, 0x4E00, 0x9FA5) || c == 0x3007 || BETWEEN(c, 0x3021, 0x3029);
  383. }
  384. static const Node pCombiningChar[] = {
  385.         { 0x0300, 0x0345 }, { 0x0360, 0x0361 }, { 0x0483, 0x0486 }, { 0x0591, 0x05A1 },
  386.         { 0x05A3, 0x05B9 }, { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
  387.         { 0x05C4, 0x05C4 }, { 0x064B, 0x0652 }, { 0x0670, 0x0670 }, { 0x06D6, 0x06DC },
  388.         { 0x06DD, 0x06DF }, { 0x06E0, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
  389.         { 0x0901, 0x0903 }, { 0x093C, 0x093C }, { 0x093E, 0x094C }, { 0x094D, 0x094D },
  390.         { 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0983 }, { 0x09BC, 0x09BC },
  391.         { 0x09BE, 0x09BE }, { 0x09BF, 0x09BF }, { 0x09C0, 0x09C4 }, { 0x09C7, 0x09C8 },
  392.         { 0x09CB, 0x09CD }, { 0x09D7, 0x09D7 }, { 0x09E2, 0x09E3 }, { 0x0A02, 0x0A02 },
  393.         { 0x0A3C, 0x0A3C }, { 0x0A3E, 0x0A3E }, { 0x0A3F, 0x0A3F }, { 0x0A40, 0x0A42 },
  394.         { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A83 },
  395.         { 0x0ABC, 0x0ABC }, { 0x0ABE, 0x0AC5 }, { 0x0AC7, 0x0AC9 }, { 0x0ACB, 0x0ACD },
  396.         { 0x0B01, 0x0B03 }, { 0x0B3C, 0x0B3C }, { 0x0B3E, 0x0B43 }, { 0x0B47, 0x0B48 },
  397.         { 0x0B4B, 0x0B4D }, { 0x0B56, 0x0B57 }, { 0x0B82, 0x0B83 }, { 0x0BBE, 0x0BC2 },
  398.         { 0x0BC6, 0x0BC8 }, { 0x0BCA, 0x0BCD }, { 0x0BD7, 0x0BD7 }, { 0x0C01, 0x0C03 },
  399.         { 0x0C3E, 0x0C44 }, { 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 },
  400.         { 0x0C82, 0x0C83 }, { 0x0CBE, 0x0CC4 }, { 0x0CC6, 0x0CC8 }, { 0x0CCA, 0x0CCD },
  401.         { 0x0CD5, 0x0CD6 }, { 0x0D02, 0x0D03 }, { 0x0D3E, 0x0D43 }, { 0x0D46, 0x0D48 },
  402.         { 0x0D4A, 0x0D4D }, { 0x0D57, 0x0D57 }, { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A },
  403.         { 0x0E47, 0x0E4E }, { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC },
  404.         { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 },
  405.         { 0x0F39, 0x0F39 }, { 0x0F3E, 0x0F3E }, { 0x0F3F, 0x0F3F }, { 0x0F71, 0x0F84 },
  406.         { 0x0F86, 0x0F8B }, { 0x0F90, 0x0F95 }, { 0x0F97, 0x0F97 }, { 0x0F99, 0x0FAD },
  407.         { 0x0FB1, 0x0FB7 }, { 0x0FB9, 0x0FB9 }, { 0x20D0, 0x20DC }, { 0x20E1, 0x20E1 },
  408.         { 0x302A, 0x302F }, { 0x3099, 0x3099 }, { 0x309A, 0x309A }
  409. };
  410. static const UINT32 ulCombiningCharCount = 95;
  411. inline BOOL UTF16Valid::IsCombiningChar(const UINT16 c)
  412. {
  413.     return (bsearch(&c, pCombiningChar, sizeof(pCombiningChar)/sizeof(Node), sizeof(Node), compare) ? TRUE : FALSE );
  414. }
  415. static const Node pDigitChar[] = {
  416.         { 0x0030, 0x0039 }, { 0x0660, 0x0669 }, { 0x06F0, 0x06F9 }, { 0x0966, 0x096F },
  417.         { 0x09E6, 0x09EF }, { 0x0A66, 0x0A6F }, { 0x0AE6, 0x0AEF }, { 0x0B66, 0x0B6F },
  418.         { 0x0BE7, 0x0BEF }, { 0x0C66, 0x0C6F }, { 0x0CE6, 0x0CEF }, { 0x0D66, 0x0D6F },
  419.         { 0x0E50, 0x0E59 }, { 0x0ED0, 0x0ED9 }, { 0x0F20, 0x0F29 }
  420. };
  421. // XXXNH: this doesn't appear to be used anywhere!
  422. //UINT32 ulDigitCharCount = 15;
  423. inline BOOL UTF16Valid::IsDigit(const UINT16 c)
  424. {
  425.     return (bsearch(&c, pDigitChar, sizeof(pDigitChar)/sizeof(Node), sizeof(Node), compare) ? TRUE : FALSE );
  426. }
  427. inline BOOL UTF16Valid::IsExtender(const UINT16 c)
  428. {
  429.     return c == 0xB7 || c == 0x02D0 || c == 0x02D1 
  430.     || c == 0x0387 || c == 0x0640 || c == 0x0E46 
  431.     || c == 0x0EC6 || 0x3005 || BETWEEN(c, 0x3031, 0x3035)
  432.     || BETWEEN(c, 0x309D, 0x309E) || BETWEEN(c, 0x30FC, 0x30FE);
  433. }
  434. #ifdef XXXJHUG
  435. void OutputTree(char* name, char* array)
  436. {
  437.     printf("nn");
  438.     printf("static const Node p%s[] = { nt", name);
  439.     int num = -1;
  440.     char* seps = "[] |";
  441.     char* token = strtok( array, seps);
  442.     int count = 0;
  443.     while( token != NULL )
  444.     {
  445. count++;
  446. if ( num == 3 )
  447. {
  448.     printf("nt");
  449.     num = 0;
  450. }
  451. else
  452. {
  453.     num++;
  454. }
  455. if ( *(token + 6) == '-' )
  456. {
  457.     // range
  458.     token[6] = '';
  459.     token++;
  460.     printf("{ 0%s, 0%s }, ", token, token+7);
  461. }
  462. else
  463. {
  464.     // single value.
  465.     token++;
  466.     printf("{ 0%s, 0%s }, ", token, token);
  467. }
  468. /* Get next token: */
  469. token = strtok( NULL, seps );
  470.     }
  471.     printf("n};n");
  472.     printf("UINT32 ul%sCount = %d;n", name, count);
  473. }
  474. void main()
  475. {
  476.     // output static binary trees..
  477.     char baseChar[] = "[#x0041-#x005A] | [#x0061-#x007A] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | [#x00F8-#x00FF] | [#x0100-#x0131] | [#x0134-#x013E] | [#x0141-#x0148] | [#x014A-#x017E] | [#x0180-#x01C3] | [#x01CD-#x01F0] | [#x01F4-#x01F5] | [#x01FA-#x0217] | [#x0250-#x02A8] | [#x02BB-#x02C1] | #x0386 | [#x0388-#x038A] | #x038C | [#x038E-#x03A1] | [#x03A3-#x03CE] | [#x03D0-#x03D6] | #x03DA | #x03DC | #x03DE | #x03E0 | [#x03E2-#x03F3] | [#x0401-#x040C] | [#x040E-#x044F] | [#x0451-#x045C] | [#x045E-#x0481] | [#x0490-#x04C4] | [#x04C7-#x04C8] | [#x04CB-#x04CC] | [#x04D0-#x04EB] | [#x04EE-#x04F5] | [#x04F8-#x04F9] | [#x0531-#x0556] | #x0559 | [#x0561-#x0586] | [#x05D0-#x05EA] | [#x05F0-#x05F2] | [#x0621-#x063A] | [#x0641-#x064A] | [#x0671-#x06B7] | [#x06BA-#x06BE] | [#x06C0-#x06CE] | [#x06D0-#x06D3] | #x06D5 | [#x06E5-#x06E6] | [#x0905-#x0939] | #x093D | [#x0958-#x0961] | [#x0985-#x098C] | [#x098F-#x0990] | [#x0993-#x09A8] | [#x09AA-#x09B0] | #x09B2 | [#x09B6-#x09B9] | [#x09DC-#x09DD] | [#x09DF-#x09E1] | [#x09F0-#x09F1] | [#x0A05-#x0A0A] | [#x0A0F-#x0A10] | [#x0A13-#x0A28] | [#x0A2A-#x0A30] | [#x0A32-#x0A33] | [#x0A35-#x0A36] | [#x0A38-#x0A39] | [#x0A59-#x0A5C] | #x0A5E | [#x0A72-#x0A74] | [#x0A85-#x0A8B] | #x0A8D | [#x0A8F-#x0A91] | [#x0A93-#x0AA8] | [#x0AAA-#x0AB0] | [#x0AB2-#x0AB3] | [#x0AB5-#x0AB9] | #x0ABD | #x0AE0 | "
  478. "[#x0B05-#x0B0C] | [#x0B0F-#x0B10] | [#x0B13-#x0B28] | [#x0B2A-#x0B30] | [#x0B32-#x0B33] | [#x0B36-#x0B39] | #x0B3D | [#x0B5C-#x0B5D] | [#x0B5F-#x0B61] | [#x0B85-#x0B8A] | [#x0B8E-#x0B90] | [#x0B92-#x0B95] | [#x0B99-#x0B9A] | #x0B9C | [#x0B9E-#x0B9F] | [#x0BA3-#x0BA4] | [#x0BA8-#x0BAA] | [#x0BAE-#x0BB5] | [#x0BB7-#x0BB9] | [#x0C05-#x0C0C] | [#x0C0E-#x0C10] | [#x0C12-#x0C28] | [#x0C2A-#x0C33] | [#x0C35-#x0C39] | [#x0C60-#x0C61] | [#x0C85-#x0C8C] | [#x0C8E-#x0C90] | [#x0C92-#x0CA8] | [#x0CAA-#x0CB3] | [#x0CB5-#x0CB9] | #x0CDE | [#x0CE0-#x0CE1] | [#x0D05-#x0D0C] | [#x0D0E-#x0D10] | [#x0D12-#x0D28] | [#x0D2A-#x0D39] | [#x0D60-#x0D61] | [#x0E01-#x0E2E] | #x0E30 | [#x0E32-#x0E33] | [#x0E40-#x0E45] | [#x0E81-#x0E82] | #x0E84 | [#x0E87-#x0E88] | #x0E8A | #x0E8D | [#x0E94-#x0E97] | [#x0E99-#x0E9F] | [#x0EA1-#x0EA3] | #x0EA5 | #x0EA7 | [#x0EAA-#x0EAB] | [#x0EAD-#x0EAE] | #x0EB0 | [#x0EB2-#x0EB3] | #x0EBD | [#x0EC0-#x0EC4] | [#x0F40-#x0F47] | [#x0F49-#x0F69] | [#x10A0-#x10C5] | [#x10D0-#x10F6] | #x1100 | [#x1102-#x1103] | [#x1105-#x1107] | #x1109 | [#x110B-#x110C] | [#x110E-#x1112] | #x113C | #x113E | #x1140 | #x114C | #x114E | #x1150 | [#x1154-#x1155] | #x1159 | [#x115F-#x1161] | #x1163 | #x1165 | #x1167 | #x1169 | [#x116D-#x116E] | [#x1172-#x1173] | #x1175 | #x119E | #x11A8 | #x11AB | [#x11AE-#x11AF] | [#x11B7-#x11B8] | #x11BA | [#x11BC-#x11C2] | #x11EB | #x11F0 | #x11F9 | [#x1E00-#x1E9B] | [#x1EA0-#x1EF9] | [#x1F00-#x1F15] | [#x1F18-#x1F1D] | [#x1F20-#x1F45] | [#x1F48-#x1F4D] | [#x1F50-#x1F57] | #x1F59 | #x1F5B | #x1F5D | [#x1F5F-#x1F7D] | [#x1F80-#x1FB4] | [#x1FB6-#x1FBC] | #x1FBE | [#x1FC2-#x1FC4] | [#x1FC6-#x1FCC] | [#x1FD0-#x1FD3] | [#x1FD6-#x1FDB] | [#x1FE0-#x1FEC] | [#x1FF2-#x1FF4] | [#x1FF6-#x1FFC] | #x2126 | [#x212A-#x212B] | #x212E | [#x2180-#x2182] | [#x3041-#x3094] | [#x30A1-#x30FA] | [#x3105-#x312C] | [#xAC00-#xD7A3]";
  479.     
  480.     char combiningChar[] = "[#x0300-#x0345] | [#x0360-#x0361] | [#x0483-#x0486] | [#x0591-#x05A1] | [#x05A3-#x05B9] | [#x05BB-#x05BD] | #x05BF | [#x05C1-#x05C2] | #x05C4 | [#x064B-#x0652] | #x0670 | [#x06D6-#x06DC] | [#x06DD-#x06DF] | [#x06E0-#x06E4] | [#x06E7-#x06E8] | [#x06EA-#x06ED] | [#x0901-#x0903] | #x093C | [#x093E-#x094C] | #x094D | [#x0951-#x0954] | [#x0962-#x0963] | [#x0981-#x0983] | #x09BC | #x09BE | #x09BF | [#x09C0-#x09C4] | [#x09C7-#x09C8] | [#x09CB-#x09CD] | #x09D7 | [#x09E2-#x09E3] | #x0A02 | #x0A3C | #x0A3E | #x0A3F | [#x0A40-#x0A42] | [#x0A47-#x0A48] | [#x0A4B-#x0A4D] | [#x0A70-#x0A71] | [#x0A81-#x0A83] | #x0ABC | [#x0ABE-#x0AC5] | [#x0AC7-#x0AC9] | [#x0ACB-#x0ACD] | [#x0B01-#x0B03] | #x0B3C | [#x0B3E-#x0B43] | [#x0B47-#x0B48] | [#x0B4B-#x0B4D] | [#x0B56-#x0B57] | [#x0B82-#x0B83] | [#x0BBE-#x0BC2] | [#x0BC6-#x0BC8] | [#x0BCA-#x0BCD] | #x0BD7 | [#x0C01-#x0C03] | [#x0C3E-#x0C44] | [#x0C46-#x0C48] | [#x0C4A-#x0C4D] | [#x0C55-#x0C56] | [#x0C82-#x0C83] | [#x0CBE-#x0CC4] | [#x0CC6-#x0CC8] | [#x0CCA-#x0CCD] | [#x0CD5-#x0CD6] | [#x0D02-#x0D03] | [#x0D3E-#x0D43] | [#x0D46-#x0D48] | [#x0D4A-#x0D4D] | #x0D57 | #x0E31 | [#x0E34-#x0E3A] | [#x0E47-#x0E4E] | #x0EB1 | [#x0EB4-#x0EB9] | [#x0EBB-#x0EBC] | [#x0EC8-#x0ECD] | [#x0F18-#x0F19] | #x0F35 | #x0F37 | #x0F39 | #x0F3E | #x0F3F | [#x0F71-#x0F84] | [#x0F86-#x0F8B] | [#x0F90-#x0F95] | #x0F97 | [#x0F99-#x0FAD] | [#x0FB1-#x0FB7] | #x0FB9 | [#x20D0-#x20DC] | #x20E1 | [#x302A-#x302F] | #x3099 | #x309A";
  481.     char digitChar[] = "[#x0030-#x0039] | [#x0660-#x0669] | [#x06F0-#x06F9] | [#x0966-#x096F] | [#x09E6-#x09EF] | [#x0A66-#x0A6F] | [#x0AE6-#x0AEF] | [#x0B66-#x0B6F] | [#x0BE7-#x0BEF] | [#x0C66-#x0C6F] | [#x0CE6-#x0CEF] | [#x0D66-#x0D6F] | [#x0E50-#x0E59] | [#x0ED0-#x0ED9] | [#x0F20-#x0F29]";
  482.     
  483.     OutputTree("BaseChar", baseChar);
  484.     OutputTree("CombiningChar", combiningChar);
  485.     OutputTree("DigitChar", digitChar);
  486.     BOOL inRange = FALSE;
  487.     int count = 0;
  488.     for ( const UINT16 i = 0; i < 0xFFFF; ++i )
  489.     {
  490. BOOL b = UTF16Valid::IsBaseChar(i);
  491. if ( ( b && !inRange) || ( !b && inRange ) )
  492. {
  493.     printf("0x%X, ", i);
  494.     if ( count == 8 )
  495.     {
  496. printf("n");
  497. count = 0;
  498.     }
  499.     count++;
  500. }
  501. inRange = b;
  502.     }
  503.     printf("nn");
  504.     inRange = FALSE;
  505.     for ( i = 0; i < 0xFFFF; ++i )
  506.     {
  507. BOOL b = UTF16Valid::IsCombiningChar(i);
  508. if ( ( b && !inRange) || ( !b && inRange ) )
  509. {
  510.     printf("0x%X, ", i);
  511.     if ( count == 8 )
  512.     {
  513. printf("n");
  514. count = 0;
  515.     }
  516.     count++;
  517. }
  518. inRange = b;
  519.     }
  520.     printf("nn");
  521.     inRange = FALSE;
  522.     for ( i = 0; i < 0xFFFF; ++i )
  523.     {
  524. BOOL b = UTF16Valid::IsDigit(i);
  525. if ( ( b && !inRange) || ( !b && inRange ) )
  526. {
  527.     printf("0x%X, ", i);
  528.     if ( count == 8 )
  529.     {
  530. printf("n");
  531. count = 0;
  532.     }
  533.     count++;
  534. }
  535. inRange = b;
  536.     }
  537.     printf("nn");
  538. }
  539. #endif