utf8.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:64k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. #ifdef DEBUG
  34. static const char CVS_ID[] = "@(#) $RCSfile: utf8.c,v $ $Revision: 1.2 $ $Date: 2000/04/04 02:36:46 $ $Name: NSS_3_1_1_RTM $";
  35. #endif /* DEBUG */
  36. #include "seccomon.h"
  37. #include "secport.h"
  38. /*
  39.  * Define this if you want to support UTF-16 in UCS-2
  40.  */
  41. #define UTF16
  42. /*
  43.  * From RFC 2044:
  44.  *
  45.  * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
  46.  * 0000 0000-0000 007F   0xxxxxxx
  47.  * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
  48.  * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
  49.  * 0001 0000-001F FFFF   11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  50.  * 0020 0000-03FF FFFF   111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  51.  * 0400 0000-7FFF FFFF   1111110x 10xxxxxx ... 10xxxxxx
  52.  */  
  53. /*
  54.  * From http://www.imc.org/draft-hoffman-utf16
  55.  *
  56.  * For U on [0x00010000,0x0010FFFF]:  Let U' = U - 0x00010000
  57.  *
  58.  * U' = yyyyyyyyyyxxxxxxxxxx
  59.  * W1 = 110110yyyyyyyyyy
  60.  * W2 = 110111xxxxxxxxxx
  61.  */
  62. /*
  63.  * This code is assuming NETWORK BYTE ORDER for the 16- and 32-bit
  64.  * character values.  If you wish to use this code for working with
  65.  * host byte order values, define the following:
  66.  *
  67.  * #if IS_BIG_ENDIAN
  68.  * #define L_0 0
  69.  * #define L_1 1
  70.  * #define L_2 2
  71.  * #define L_3 3
  72.  * #define H_0 0
  73.  * #define H_1 1
  74.  * #else / * not everyone has elif * /
  75.  * #if IS_LITTLE_ENDIAN
  76.  * #define L_0 3
  77.  * #define L_1 2
  78.  * #define L_2 1
  79.  * #define L_3 0
  80.  * #define H_0 1
  81.  * #define H_1 0
  82.  * #else
  83.  * #error "PDP and NUXI support deferred"
  84.  * #endif / * IS_LITTLE_ENDIAN * /
  85.  * #endif / * IS_BIG_ENDIAN * /
  86.  */
  87. #define L_0 0
  88. #define L_1 1
  89. #define L_2 2
  90. #define L_3 3
  91. #define H_0 0
  92. #define H_1 1
  93. PR_IMPLEMENT(PRBool)
  94. sec_port_ucs4_utf8_conversion_function
  95. (
  96.   PRBool toUnicode,
  97.   unsigned char *inBuf,
  98.   unsigned int inBufLen,
  99.   unsigned char *outBuf,
  100.   unsigned int maxOutBufLen,
  101.   unsigned int *outBufLen
  102. )
  103. {
  104. #ifndef TEST_UTF8
  105.   PORT_Assert((unsigned int *)NULL != outBufLen);
  106. #endif /* TEST_UTF8 */
  107.   if( toUnicode ) {
  108.     unsigned int i, len = 0;
  109.     for( i = 0; i < inBufLen; ) {
  110.       if( (inBuf[i] & 0x80) == 0x00 ) i += 1;
  111.       else if( (inBuf[i] & 0xE0) == 0xC0 ) i += 2;
  112.       else if( (inBuf[i] & 0xF0) == 0xE0 ) i += 3;
  113.       else if( (inBuf[i] & 0xF8) == 0xF0 ) i += 4;
  114.       else if( (inBuf[i] & 0xFC) == 0xF8 ) i += 5;
  115.       else if( (inBuf[i] & 0xFE) == 0xFC ) i += 6;
  116.       else return PR_FALSE;
  117.       len += 4;
  118.     }
  119.     if( len > maxOutBufLen ) {
  120.       *outBufLen = len;
  121.       return PR_FALSE;
  122.     }
  123.     len = 0;
  124.     for( i = 0; i < inBufLen; ) {
  125.       if( (inBuf[i] & 0x80) == 0x00 ) {
  126.         /* 0000 0000-0000 007F <- 0xxxxxx */
  127.         /* 0abcdefg -> 
  128.            00000000 00000000 00000000 0abcdefg */
  129.         outBuf[len+L_0] = 0x00;
  130.         outBuf[len+L_1] = 0x00;
  131.         outBuf[len+L_2] = 0x00;
  132.         outBuf[len+L_3] = inBuf[i+0] & 0x7F;
  133.         i += 1;
  134.       } else if( (inBuf[i] & 0xE0) == 0xC0 ) {
  135.         if( (inBuf[i+1] & 0xC0) != 0x80 ) return PR_FALSE;
  136.         /* 0000 0080-0000 07FF <- 110xxxxx 10xxxxxx */
  137.         /* 110abcde 10fghijk ->
  138.            00000000 00000000 00000abc defghijk */
  139.         outBuf[len+L_0] = 0x00;
  140.         outBuf[len+L_1] = 0x00;
  141.         outBuf[len+L_2] = ((inBuf[i+0] & 0x1C) >> 2);
  142.         outBuf[len+L_3] = ((inBuf[i+0] & 0x03) << 6) | ((inBuf[i+1] & 0x3F) >> 0);
  143.         i += 2;
  144.       } else if( (inBuf[i] & 0xF0) == 0xE0 ) {
  145.         if( (inBuf[i+1] & 0xC0) != 0x80 ) return PR_FALSE;
  146.         if( (inBuf[i+2] & 0xC0) != 0x80 ) return PR_FALSE;
  147.         /* 0000 0800-0000 FFFF <- 1110xxxx 10xxxxxx 10xxxxxx */
  148.         /* 1110abcd 10efghij 10klmnop ->
  149.            00000000 00000000 abcdefgh ijklmnop */
  150.         outBuf[len+L_0] = 0x00;
  151.         outBuf[len+L_1] = 0x00;
  152.         outBuf[len+L_2] = ((inBuf[i+0] & 0x0F) << 4) | ((inBuf[i+1] & 0x3C) >> 2);
  153.         outBuf[len+L_3] = ((inBuf[i+1] & 0x03) << 6) | ((inBuf[i+2] & 0x3F) >> 0);
  154.         i += 3;
  155.       } else if( (inBuf[i] & 0xF8) == 0xF0 ) {
  156.         if( (inBuf[i+1] & 0xC0) != 0x80 ) return PR_FALSE;
  157.         if( (inBuf[i+2] & 0xC0) != 0x80 ) return PR_FALSE;
  158.         if( (inBuf[i+3] & 0xC0) != 0x80 ) return PR_FALSE;
  159.         /* 0001 0000-001F FFFF <- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
  160.         /* 11110abc 10defghi 10jklmno 10pqrstu -> 
  161.            00000000 000abcde fghijklm nopqrstu */
  162.            
  163.         outBuf[len+L_0] = 0x00;
  164.         outBuf[len+L_1] = ((inBuf[i+0] & 0x07) << 2) | ((inBuf[i+1] & 0x30) >> 4);
  165.         outBuf[len+L_2] = ((inBuf[i+1] & 0x0F) << 4) | ((inBuf[i+2] & 0x3C) >> 2);
  166.         outBuf[len+L_3] = ((inBuf[i+2] & 0x03) << 6) | ((inBuf[i+3] & 0x3F) >> 0);
  167.         i += 4;
  168.       } else if( (inBuf[i] & 0xFC) == 0xF8 ) {
  169.         if( (inBuf[i+1] & 0xC0) != 0x80 ) return PR_FALSE;
  170.         if( (inBuf[i+2] & 0xC0) != 0x80 ) return PR_FALSE;
  171.         if( (inBuf[i+3] & 0xC0) != 0x80 ) return PR_FALSE;
  172.         if( (inBuf[i+4] & 0xC0) != 0x80 ) return PR_FALSE;
  173.         /* 0020 0000-03FF FFFF <- 111110xx 10xxxxxx ... 10xxxxxx */
  174.         /* 111110ab 10cdefgh 10ijklmn 10opqrst 10uvwxyz -> 
  175.            000000ab cdefghij klmnopqr stuvwxyz */
  176.         outBuf[len+L_0] = inBuf[i+0] & 0x03;
  177.         outBuf[len+L_1] = ((inBuf[i+1] & 0x3F) << 2) | ((inBuf[i+2] & 0x30) >> 4);
  178.         outBuf[len+L_2] = ((inBuf[i+2] & 0x0F) << 4) | ((inBuf[i+3] & 0x3C) >> 2);
  179.         outBuf[len+L_3] = ((inBuf[i+3] & 0x03) << 6) | ((inBuf[i+4] & 0x3F) >> 0);
  180.         i += 5;
  181.       } else /* if( (inBuf[i] & 0xFE) == 0xFC ) */ {
  182.         if( (inBuf[i+1] & 0xC0) != 0x80 ) return PR_FALSE;
  183.         if( (inBuf[i+2] & 0xC0) != 0x80 ) return PR_FALSE;
  184.         if( (inBuf[i+3] & 0xC0) != 0x80 ) return PR_FALSE;
  185.         if( (inBuf[i+4] & 0xC0) != 0x80 ) return PR_FALSE;
  186.         if( (inBuf[i+5] & 0xC0) != 0x80 ) return PR_FALSE;
  187.         /* 0400 0000-7FFF FFFF <- 1111110x 10xxxxxx ... 10xxxxxx */
  188.         /* 1111110a 10bcdefg 10hijklm 10nopqrs 10tuvwxy 10zABCDE -> 
  189.            0abcdefg hijklmno pqrstuvw xyzABCDE */
  190.         outBuf[len+L_0] = ((inBuf[i+0] & 0x01) << 6) | ((inBuf[i+1] & 0x3F) >> 0);
  191.         outBuf[len+L_1] = ((inBuf[i+2] & 0x3F) << 2) | ((inBuf[i+3] & 0x30) >> 4);
  192.         outBuf[len+L_2] = ((inBuf[i+3] & 0x0F) << 4) | ((inBuf[i+4] & 0x3C) >> 2);
  193.         outBuf[len+L_3] = ((inBuf[i+4] & 0x03) << 6) | ((inBuf[i+5] & 0x3F) >> 0);
  194.         i += 6;
  195.       }
  196.       len += 4;
  197.     }
  198.     *outBufLen = len;
  199.     return PR_TRUE;
  200.   } else {
  201.     unsigned int i, len = 0;
  202.     for( i = 0; i < inBufLen; i += 4 ) {
  203.       if( inBuf[i+L_0] >= 0x04 ) len += 6;
  204.       else if( (inBuf[i+L_0] > 0x00) || (inBuf[i+L_1] >= 0x20) ) len += 5;
  205.       else if( inBuf[i+L_1] >= 0x01 ) len += 4;
  206.       else if( inBuf[i+L_2] >= 0x08 ) len += 3;
  207.       else if( (inBuf[i+L_2] > 0x00) || (inBuf[i+L_3] >= 0x80) ) len += 2;
  208.       else len += 1;
  209.     }
  210.     if( len > maxOutBufLen ) {
  211.       *outBufLen = len;
  212.       return PR_FALSE;
  213.     }
  214.     len = 0;
  215.     for( i = 0; i < inBufLen; i += 4 ) {
  216.       if( inBuf[i+L_0] >= 0x04 ) {
  217.         /* 0400 0000-7FFF FFFF -> 1111110x 10xxxxxx ... 10xxxxxx */
  218.         /* 0abcdefg hijklmno pqrstuvw xyzABCDE ->
  219.            1111110a 10bcdefg 10hijklm 10nopqrs 10tuvwxy 10zABCDE */
  220.         outBuf[len+0] = 0xFC | ((inBuf[i+L_0] & 0x40) >> 6);
  221.         outBuf[len+1] = 0x80 | ((inBuf[i+L_0] & 0x3F) >> 0);
  222.         outBuf[len+2] = 0x80 | ((inBuf[i+L_1] & 0xFC) >> 2);
  223.         outBuf[len+3] = 0x80 | ((inBuf[i+L_1] & 0x03) << 4)
  224.                              | ((inBuf[i+L_2] & 0xF0) >> 4);
  225.         outBuf[len+4] = 0x80 | ((inBuf[i+L_2] & 0x0F) << 2)
  226.                              | ((inBuf[i+L_3] & 0xC0) >> 6);
  227.         outBuf[len+5] = 0x80 | ((inBuf[i+L_3] & 0x3F) >> 0);
  228.         len += 6;
  229.       } else if( (inBuf[i+L_0] > 0x00) || (inBuf[i+L_1] >= 0x20) ) {
  230.         /* 0020 0000-03FF FFFF -> 111110xx 10xxxxxx ... 10xxxxxx */
  231.         /* 000000ab cdefghij klmnopqr stuvwxyz ->
  232.            111110ab 10cdefgh 10ijklmn 10opqrst 10uvwxyz */
  233.         outBuf[len+0] = 0xF8 | ((inBuf[i+L_0] & 0x03) >> 0);
  234.         outBuf[len+1] = 0x80 | ((inBuf[i+L_1] & 0xFC) >> 2);
  235.         outBuf[len+2] = 0x80 | ((inBuf[i+L_1] & 0x03) << 4)
  236.                              | ((inBuf[i+L_2] & 0xF0) >> 4);
  237.         outBuf[len+3] = 0x80 | ((inBuf[i+L_2] & 0x0F) << 2)
  238.                              | ((inBuf[i+L_3] & 0xC0) >> 6);
  239.         outBuf[len+4] = 0x80 | ((inBuf[i+L_3] & 0x3F) >> 0);
  240.         len += 5;
  241.       } else if( inBuf[i+L_1] >= 0x01 ) {
  242.         /* 0001 0000-001F FFFF -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
  243.         /* 00000000 000abcde fghijklm nopqrstu ->
  244.            11110abc 10defghi 10jklmno 10pqrstu */
  245.         outBuf[len+0] = 0xF0 | ((inBuf[i+L_1] & 0x1C) >> 2);
  246.         outBuf[len+1] = 0x80 | ((inBuf[i+L_1] & 0x03) << 4)
  247.                              | ((inBuf[i+L_2] & 0xF0) >> 4);
  248.         outBuf[len+2] = 0x80 | ((inBuf[i+L_2] & 0x0F) << 2)
  249.                              | ((inBuf[i+L_3] & 0xC0) >> 6);
  250.         outBuf[len+3] = 0x80 | ((inBuf[i+L_3] & 0x3F) >> 0);
  251.         len += 4;
  252.       } else if( inBuf[i+L_2] >= 0x08 ) {
  253.         /* 0000 0800-0000 FFFF -> 1110xxxx 10xxxxxx 10xxxxxx */
  254.         /* 00000000 00000000 abcdefgh ijklmnop ->
  255.            1110abcd 10efghij 10klmnop */
  256.         outBuf[len+0] = 0xE0 | ((inBuf[i+L_2] & 0xF0) >> 4);
  257.         outBuf[len+1] = 0x80 | ((inBuf[i+L_2] & 0x0F) << 2)
  258.                              | ((inBuf[i+L_3] & 0xC0) >> 6);
  259.         outBuf[len+2] = 0x80 | ((inBuf[i+L_3] & 0x3F) >> 0);
  260.         len += 3;
  261.       } else if( (inBuf[i+L_2] > 0x00) || (inBuf[i+L_3] >= 0x80) ) {
  262.         /* 0000 0080-0000 07FF -> 110xxxxx 10xxxxxx */
  263.         /* 00000000 00000000 00000abc defghijk ->
  264.            110abcde 10fghijk */
  265.         outBuf[len+0] = 0xC0 | ((inBuf[i+L_2] & 0x07) << 2)
  266.                              | ((inBuf[i+L_3] & 0xC0) >> 6);
  267.         outBuf[len+1] = 0x80 | ((inBuf[i+L_3] & 0x3F) >> 0);
  268.         len += 2;
  269.       } else {
  270.         /* 0000 0000-0000 007F -> 0xxxxxx */
  271.         /* 00000000 00000000 00000000 0abcdefg ->
  272.            0abcdefg */
  273.         outBuf[len+0] = (inBuf[i+L_3] & 0x7F);
  274.         len += 1;
  275.       }
  276.     }
  277.                             
  278.     *outBufLen = len;
  279.     return PR_TRUE;
  280.   }
  281. }
  282. PR_IMPLEMENT(PRBool)
  283. sec_port_ucs2_utf8_conversion_function
  284. (
  285.   PRBool toUnicode,
  286.   unsigned char *inBuf,
  287.   unsigned int inBufLen,
  288.   unsigned char *outBuf,
  289.   unsigned int maxOutBufLen,
  290.   unsigned int *outBufLen
  291. )
  292. {
  293. #ifndef TEST_UTF8
  294.   PORT_Assert((unsigned int *)NULL != outBufLen);
  295. #endif /* TEST_UTF8 */
  296.   if( toUnicode ) {
  297.     unsigned int i, len = 0;
  298.     for( i = 0; i < inBufLen; ) {
  299.       if( (inBuf[i] & 0x80) == 0x00 ) {
  300.         i += 1;
  301.         len += 2;
  302.       } else if( (inBuf[i] & 0xE0) == 0xC0 ) {
  303.         i += 2;
  304.         len += 2;
  305.       } else if( (inBuf[i] & 0xF0) == 0xE0 ) {
  306.         i += 3;
  307.         len += 2;
  308. #ifdef UTF16
  309.       } else if( (inBuf[i] & 0xF8) == 0xF0 ) { 
  310.         i += 4;
  311.         len += 4;
  312.         if( (inBuf[i] & 0x04) && 
  313.             ((inBuf[i] & 0x03) || (inBuf[i+1] & 0x30)) ) {
  314.           /* Not representable as UTF16 */
  315.           return PR_FALSE;
  316.         }
  317. #endif /* UTF16 */
  318.       } else return PR_FALSE;
  319.     }
  320.     if( len > maxOutBufLen ) {
  321.       *outBufLen = len;
  322.       return PR_FALSE;
  323.     }
  324.     len = 0;
  325.     for( i = 0; i < inBufLen; ) {
  326.       if( (inBuf[i] & 0x80) == 0x00 ) {
  327.         /* 0000-007F <- 0xxxxxx */
  328.         /* 0abcdefg -> 00000000 0abcdefg */
  329.         outBuf[len+H_0] = 0x00;
  330.         outBuf[len+H_1] = inBuf[i+0] & 0x7F;
  331.         i += 1;
  332.         len += 2;
  333.       } else if( (inBuf[i] & 0xE0) == 0xC0 ) {
  334.         if( (inBuf[i+1] & 0xC0) != 0x80 ) return PR_FALSE;
  335.         /* 0080-07FF <- 110xxxxx 10xxxxxx */
  336.         /* 110abcde 10fghijk -> 00000abc defghijk */
  337.         outBuf[len+H_0] = ((inBuf[i+0] & 0x1C) >> 2);
  338.         outBuf[len+H_1] = ((inBuf[i+0] & 0x03) << 6) | ((inBuf[i+1] & 0x3F) >> 0);
  339.         i += 2;
  340.         len += 2;
  341.       } else if( (inBuf[i] & 0xF0) == 0xE0 ) {
  342.         if( (inBuf[i+1] & 0xC0) != 0x80 ) return PR_FALSE;
  343.         if( (inBuf[i+2] & 0xC0) != 0x80 ) return PR_FALSE;
  344.         /* 0800-FFFF <- 1110xxxx 10xxxxxx 10xxxxxx */
  345.         /* 1110abcd 10efghij 10klmnop -> abcdefgh ijklmnop */
  346.         outBuf[len+H_0] = ((inBuf[i+0] & 0x0F) << 4) | ((inBuf[i+1] & 0x3C) >> 2);
  347.         outBuf[len+H_1] = ((inBuf[i+1] & 0x03) << 6) | ((inBuf[i+2] & 0x3F) >> 0);
  348.         i += 3;
  349.         len += 2;
  350. #ifdef UTF16
  351.       } else if( (inBuf[i] & 0xF8) == 0xF0 ) { 
  352.         int abcde, BCDE;
  353.         if( (inBuf[i+1] & 0xC0) != 0x80 ) return PR_FALSE;
  354.         if( (inBuf[i+2] & 0xC0) != 0x80 ) return PR_FALSE;
  355.         if( (inBuf[i+3] & 0xC0) != 0x80 ) return PR_FALSE;
  356.         /* 0001 0000-001F FFFF <- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
  357.         /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx -> [D800-DBFF] [DC00-DFFF] */
  358.            
  359.         /* 11110abc 10defghi 10jklmno 10pqrstu -> 
  360.            { Let 0BCDE = abcde - 1 }
  361.            110110BC DEfghijk 110111lm nopqrstu */
  362.         abcde = ((inBuf[i+0] & 0x07) << 2) | ((inBuf[i+1] & 0x30) >> 4);
  363.         BCDE = abcde - 1;
  364. #ifndef TEST_UTF8
  365.         PORT_Assert(BCDE < 0x10); /* should have been caught above */
  366. #endif /* TEST_UTF8 */
  367.         outBuf[len+0+H_0] = 0xD8 | ((BCDE & 0x0C) >> 2);
  368.         outBuf[len+0+H_1] = ((BCDE & 0x03) << 6) 
  369.                       | ((inBuf[i+1] & 0x0F) << 2)
  370.                       | ((inBuf[i+2] & 0x30) >> 4);
  371.         outBuf[len+2+H_0] = 0xDC | ((inBuf[i+2] & 0x0C) >> 2);
  372.         outBuf[len+2+H_1] = ((inBuf[i+2] & 0x03) << 6) | ((inBuf[i+3] & 0x3F) >> 0);
  373.         i += 4;
  374.         len += 4;
  375. #endif /* UTF16 */
  376.       } else return PR_FALSE;
  377.     }
  378.     *outBufLen = len;
  379.     return PR_TRUE;
  380.   } else {
  381.     unsigned int i, len = 0;
  382.     for( i = 0; i < inBufLen; i += 2 ) {
  383.       if( (inBuf[i+H_0] == 0x00) && ((inBuf[i+H_0] & 0x80) == 0x00) ) len += 1;
  384.       else if( inBuf[i+H_0] < 0x08 ) len += 2;
  385. #ifdef UTF16
  386.       else if( ((inBuf[i+0+H_0] & 0xDC) == 0xD8) ) {
  387.         if( ((inBuf[i+2+H_0] & 0xDC) == 0xDC) && ((inBufLen - i) > 2) ) {
  388.           i += 2;
  389.           len += 4;
  390.         } else {
  391.           return PR_FALSE;
  392.         }
  393.       }
  394. #endif /* UTF16 */
  395.       else len += 3;
  396.     }
  397.     if( len > maxOutBufLen ) {
  398.       *outBufLen = len;
  399.       return PR_FALSE;
  400.     }
  401.     len = 0;
  402.     for( i = 0; i < inBufLen; i += 2 ) {
  403.       if( (inBuf[i+H_0] == 0x00) && ((inBuf[i+H_1] & 0x80) == 0x00) ) {
  404.         /* 0000-007F -> 0xxxxxx */
  405.         /* 00000000 0abcdefg -> 0abcdefg */
  406.         outBuf[len] = inBuf[i+H_1] & 0x7F;
  407.         len += 1;
  408.       } else if( inBuf[i+H_0] < 0x08 ) {
  409.         /* 0080-07FF -> 110xxxxx 10xxxxxx */
  410.         /* 00000abc defghijk -> 110abcde 10fghijk */
  411.         outBuf[len+0] = 0xC0 | ((inBuf[i+H_0] & 0x07) << 2) 
  412.                              | ((inBuf[i+H_1] & 0xC0) >> 6);
  413.         outBuf[len+1] = 0x80 | ((inBuf[i+H_1] & 0x3F) >> 0);
  414.         len += 2;
  415. #ifdef UTF16
  416.       } else if( (inBuf[i+H_0] & 0xDC) == 0xD8 ) {
  417.         int abcde, BCDE;
  418. #ifndef TEST_UTF8
  419.         PORT_Assert(((inBuf[i+2+H_0] & 0xDC) == 0xDC) && ((inBufLen - i) > 2));
  420. #endif /* TEST_UTF8 */
  421.         /* D800-DBFF DC00-DFFF -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
  422.         /* 110110BC DEfghijk 110111lm nopqrstu ->
  423.            { Let abcde = BCDE + 1 }
  424.            11110abc 10defghi 10jklmno 10pqrstu */
  425.         BCDE = ((inBuf[i+H_0] & 0x03) << 2) | ((inBuf[i+H_1] & 0xC0) >> 6);
  426.         abcde = BCDE + 1;
  427.         outBuf[len+0] = 0xF0 | ((abcde & 0x1C) >> 2);
  428.         outBuf[len+1] = 0x80 | ((abcde & 0x03) << 4) 
  429.                              | ((inBuf[i+0+H_1] & 0x3C) >> 2);
  430.         outBuf[len+2] = 0x80 | ((inBuf[i+0+H_1] & 0x03) << 4)
  431.                              | ((inBuf[i+2+H_0] & 0x03) << 2)
  432.                              | ((inBuf[i+2+H_1] & 0xC0) >> 6);
  433.         outBuf[len+3] = 0x80 | ((inBuf[i+2+H_1] & 0x3F) >> 0);
  434.         i += 2;
  435.         len += 4;
  436. #endif /* UTF16 */
  437.       } else {
  438.         /* 0800-FFFF -> 1110xxxx 10xxxxxx 10xxxxxx */
  439.         /* abcdefgh ijklmnop -> 1110abcd 10efghij 10klmnop */
  440.         outBuf[len+0] = 0xE0 | ((inBuf[i+H_0] & 0xF0) >> 4);
  441.         outBuf[len+1] = 0x80 | ((inBuf[i+H_0] & 0x0F) << 2) 
  442.                              | ((inBuf[i+H_1] & 0xC0) >> 6);
  443.         outBuf[len+2] = 0x80 | ((inBuf[i+H_1] & 0x3F) >> 0);
  444.         len += 3;
  445.       }
  446.     }
  447.     *outBufLen = len;
  448.     return PR_TRUE;
  449.   }
  450. }
  451. #ifdef TEST_UTF8
  452. #include <stdio.h>
  453. #include <string.h>
  454. #include <stdlib.h>
  455. #include <netinet/in.h> /* for htonl and htons */
  456. /*
  457.  * UCS-4 vectors
  458.  */
  459. struct ucs4 {
  460.   PRUint32 c;
  461.   char *utf8;
  462. };
  463. /*
  464.  * UCS-2 vectors
  465.  */
  466. struct ucs2 {
  467.   PRUint16 c;
  468.   char *utf8;
  469. };
  470. #ifdef UTF16
  471. /*
  472.  * UTF-16 vectors
  473.  */
  474. struct utf16 {
  475.   PRUint32 c;
  476.   PRUint16 w[2];
  477. };
  478. #endif /* UTF16 */
  479. /*
  480.  * UCS-4 vectors
  481.  */
  482. struct ucs4 ucs4[] = {
  483.   { 0x00000001, "x01" },
  484.   { 0x00000002, "x02" },
  485.   { 0x00000003, "x03" },
  486.   { 0x00000004, "x04" },
  487.   { 0x00000007, "x07" },
  488.   { 0x00000008, "x08" },
  489.   { 0x0000000F, "x0F" },
  490.   { 0x00000010, "x10" },
  491.   { 0x0000001F, "x1F" },
  492.   { 0x00000020, "x20" },
  493.   { 0x0000003F, "x3F" },
  494.   { 0x00000040, "x40" },
  495.   { 0x0000007F, "x7F" },
  496.           
  497.   { 0x00000080, "xC2x80" },
  498.   { 0x00000081, "xC2x81" },
  499.   { 0x00000082, "xC2x82" },
  500.   { 0x00000084, "xC2x84" },
  501.   { 0x00000088, "xC2x88" },
  502.   { 0x00000090, "xC2x90" },
  503.   { 0x000000A0, "xC2xA0" },
  504.   { 0x000000C0, "xC3x80" },
  505.   { 0x000000FF, "xC3xBF" },
  506.   { 0x00000100, "xC4x80" },
  507.   { 0x00000101, "xC4x81" },
  508.   { 0x00000102, "xC4x82" },
  509.   { 0x00000104, "xC4x84" },
  510.   { 0x00000108, "xC4x88" },
  511.   { 0x00000110, "xC4x90" },
  512.   { 0x00000120, "xC4xA0" },
  513.   { 0x00000140, "xC5x80" },
  514.   { 0x00000180, "xC6x80" },
  515.   { 0x000001FF, "xC7xBF" },
  516.   { 0x00000200, "xC8x80" },
  517.   { 0x00000201, "xC8x81" },
  518.   { 0x00000202, "xC8x82" },
  519.   { 0x00000204, "xC8x84" },
  520.   { 0x00000208, "xC8x88" },
  521.   { 0x00000210, "xC8x90" },
  522.   { 0x00000220, "xC8xA0" },
  523.   { 0x00000240, "xC9x80" },
  524.   { 0x00000280, "xCAx80" },
  525.   { 0x00000300, "xCCx80" },
  526.   { 0x000003FF, "xCFxBF" },
  527.   { 0x00000400, "xD0x80" },
  528.   { 0x00000401, "xD0x81" },
  529.   { 0x00000402, "xD0x82" },
  530.   { 0x00000404, "xD0x84" },
  531.   { 0x00000408, "xD0x88" },
  532.   { 0x00000410, "xD0x90" },
  533.   { 0x00000420, "xD0xA0" },
  534.   { 0x00000440, "xD1x80" },
  535.   { 0x00000480, "xD2x80" },
  536.   { 0x00000500, "xD4x80" },
  537.   { 0x00000600, "xD8x80" },
  538.   { 0x000007FF, "xDFxBF" },
  539.           
  540.   { 0x00000800, "xE0xA0x80" },
  541.   { 0x00000801, "xE0xA0x81" },
  542.   { 0x00000802, "xE0xA0x82" },
  543.   { 0x00000804, "xE0xA0x84" },
  544.   { 0x00000808, "xE0xA0x88" },
  545.   { 0x00000810, "xE0xA0x90" },
  546.   { 0x00000820, "xE0xA0xA0" },
  547.   { 0x00000840, "xE0xA1x80" },
  548.   { 0x00000880, "xE0xA2x80" },
  549.   { 0x00000900, "xE0xA4x80" },
  550.   { 0x00000A00, "xE0xA8x80" },
  551.   { 0x00000C00, "xE0xB0x80" },
  552.   { 0x00000FFF, "xE0xBFxBF" },
  553.   { 0x00001000, "xE1x80x80" },
  554.   { 0x00001001, "xE1x80x81" },
  555.   { 0x00001002, "xE1x80x82" },
  556.   { 0x00001004, "xE1x80x84" },
  557.   { 0x00001008, "xE1x80x88" },
  558.   { 0x00001010, "xE1x80x90" },
  559.   { 0x00001020, "xE1x80xA0" },
  560.   { 0x00001040, "xE1x81x80" },
  561.   { 0x00001080, "xE1x82x80" },
  562.   { 0x00001100, "xE1x84x80" },
  563.   { 0x00001200, "xE1x88x80" },
  564.   { 0x00001400, "xE1x90x80" },
  565.   { 0x00001800, "xE1xA0x80" },
  566.   { 0x00001FFF, "xE1xBFxBF" },
  567.   { 0x00002000, "xE2x80x80" },
  568.   { 0x00002001, "xE2x80x81" },
  569.   { 0x00002002, "xE2x80x82" },
  570.   { 0x00002004, "xE2x80x84" },
  571.   { 0x00002008, "xE2x80x88" },
  572.   { 0x00002010, "xE2x80x90" },
  573.   { 0x00002020, "xE2x80xA0" },
  574.   { 0x00002040, "xE2x81x80" },
  575.   { 0x00002080, "xE2x82x80" },
  576.   { 0x00002100, "xE2x84x80" },
  577.   { 0x00002200, "xE2x88x80" },
  578.   { 0x00002400, "xE2x90x80" },
  579.   { 0x00002800, "xE2xA0x80" },
  580.   { 0x00003000, "xE3x80x80" },
  581.   { 0x00003FFF, "xE3xBFxBF" },
  582.   { 0x00004000, "xE4x80x80" },
  583.   { 0x00004001, "xE4x80x81" },
  584.   { 0x00004002, "xE4x80x82" },
  585.   { 0x00004004, "xE4x80x84" },
  586.   { 0x00004008, "xE4x80x88" },
  587.   { 0x00004010, "xE4x80x90" },
  588.   { 0x00004020, "xE4x80xA0" },
  589.   { 0x00004040, "xE4x81x80" },
  590.   { 0x00004080, "xE4x82x80" },
  591.   { 0x00004100, "xE4x84x80" },
  592.   { 0x00004200, "xE4x88x80" },
  593.   { 0x00004400, "xE4x90x80" },
  594.   { 0x00004800, "xE4xA0x80" },
  595.   { 0x00005000, "xE5x80x80" },
  596.   { 0x00006000, "xE6x80x80" },
  597.   { 0x00007FFF, "xE7xBFxBF" },
  598.   { 0x00008000, "xE8x80x80" },
  599.   { 0x00008001, "xE8x80x81" },
  600.   { 0x00008002, "xE8x80x82" },
  601.   { 0x00008004, "xE8x80x84" },
  602.   { 0x00008008, "xE8x80x88" },
  603.   { 0x00008010, "xE8x80x90" },
  604.   { 0x00008020, "xE8x80xA0" },
  605.   { 0x00008040, "xE8x81x80" },
  606.   { 0x00008080, "xE8x82x80" },
  607.   { 0x00008100, "xE8x84x80" },
  608.   { 0x00008200, "xE8x88x80" },
  609.   { 0x00008400, "xE8x90x80" },
  610.   { 0x00008800, "xE8xA0x80" },
  611.   { 0x00009000, "xE9x80x80" },
  612.   { 0x0000A000, "xEAx80x80" },
  613.   { 0x0000C000, "xECx80x80" },
  614.   { 0x0000FFFF, "xEFxBFxBF" },
  615.           
  616.   { 0x00010000, "xF0x90x80x80" },
  617.   { 0x00010001, "xF0x90x80x81" },
  618.   { 0x00010002, "xF0x90x80x82" },
  619.   { 0x00010004, "xF0x90x80x84" },
  620.   { 0x00010008, "xF0x90x80x88" },
  621.   { 0x00010010, "xF0x90x80x90" },
  622.   { 0x00010020, "xF0x90x80xA0" },
  623.   { 0x00010040, "xF0x90x81x80" },
  624.   { 0x00010080, "xF0x90x82x80" },
  625.   { 0x00010100, "xF0x90x84x80" },
  626.   { 0x00010200, "xF0x90x88x80" },
  627.   { 0x00010400, "xF0x90x90x80" },
  628.   { 0x00010800, "xF0x90xA0x80" },
  629.   { 0x00011000, "xF0x91x80x80" },
  630.   { 0x00012000, "xF0x92x80x80" },
  631.   { 0x00014000, "xF0x94x80x80" },
  632.   { 0x00018000, "xF0x98x80x80" },
  633.   { 0x0001FFFF, "xF0x9FxBFxBF" },
  634.   { 0x00020000, "xF0xA0x80x80" },
  635.   { 0x00020001, "xF0xA0x80x81" },
  636.   { 0x00020002, "xF0xA0x80x82" },
  637.   { 0x00020004, "xF0xA0x80x84" },
  638.   { 0x00020008, "xF0xA0x80x88" },
  639.   { 0x00020010, "xF0xA0x80x90" },
  640.   { 0x00020020, "xF0xA0x80xA0" },
  641.   { 0x00020040, "xF0xA0x81x80" },
  642.   { 0x00020080, "xF0xA0x82x80" },
  643.   { 0x00020100, "xF0xA0x84x80" },
  644.   { 0x00020200, "xF0xA0x88x80" },
  645.   { 0x00020400, "xF0xA0x90x80" },
  646.   { 0x00020800, "xF0xA0xA0x80" },
  647.   { 0x00021000, "xF0xA1x80x80" },
  648.   { 0x00022000, "xF0xA2x80x80" },
  649.   { 0x00024000, "xF0xA4x80x80" },
  650.   { 0x00028000, "xF0xA8x80x80" },
  651.   { 0x00030000, "xF0xB0x80x80" },
  652.   { 0x0003FFFF, "xF0xBFxBFxBF" },
  653.   { 0x00040000, "xF1x80x80x80" },
  654.   { 0x00040001, "xF1x80x80x81" },
  655.   { 0x00040002, "xF1x80x80x82" },
  656.   { 0x00040004, "xF1x80x80x84" },
  657.   { 0x00040008, "xF1x80x80x88" },
  658.   { 0x00040010, "xF1x80x80x90" },
  659.   { 0x00040020, "xF1x80x80xA0" },
  660.   { 0x00040040, "xF1x80x81x80" },
  661.   { 0x00040080, "xF1x80x82x80" },
  662.   { 0x00040100, "xF1x80x84x80" },
  663.   { 0x00040200, "xF1x80x88x80" },
  664.   { 0x00040400, "xF1x80x90x80" },
  665.   { 0x00040800, "xF1x80xA0x80" },
  666.   { 0x00041000, "xF1x81x80x80" },
  667.   { 0x00042000, "xF1x82x80x80" },
  668.   { 0x00044000, "xF1x84x80x80" },
  669.   { 0x00048000, "xF1x88x80x80" },
  670.   { 0x00050000, "xF1x90x80x80" },
  671.   { 0x00060000, "xF1xA0x80x80" },
  672.   { 0x0007FFFF, "xF1xBFxBFxBF" },
  673.   { 0x00080000, "xF2x80x80x80" },
  674.   { 0x00080001, "xF2x80x80x81" },
  675.   { 0x00080002, "xF2x80x80x82" },
  676.   { 0x00080004, "xF2x80x80x84" },
  677.   { 0x00080008, "xF2x80x80x88" },
  678.   { 0x00080010, "xF2x80x80x90" },
  679.   { 0x00080020, "xF2x80x80xA0" },
  680.   { 0x00080040, "xF2x80x81x80" },
  681.   { 0x00080080, "xF2x80x82x80" },
  682.   { 0x00080100, "xF2x80x84x80" },
  683.   { 0x00080200, "xF2x80x88x80" },
  684.   { 0x00080400, "xF2x80x90x80" },
  685.   { 0x00080800, "xF2x80xA0x80" },
  686.   { 0x00081000, "xF2x81x80x80" },
  687.   { 0x00082000, "xF2x82x80x80" },
  688.   { 0x00084000, "xF2x84x80x80" },
  689.   { 0x00088000, "xF2x88x80x80" },
  690.   { 0x00090000, "xF2x90x80x80" },
  691.   { 0x000A0000, "xF2xA0x80x80" },
  692.   { 0x000C0000, "xF3x80x80x80" },
  693.   { 0x000FFFFF, "xF3xBFxBFxBF" },
  694.   { 0x00100000, "xF4x80x80x80" },
  695.   { 0x00100001, "xF4x80x80x81" },
  696.   { 0x00100002, "xF4x80x80x82" },
  697.   { 0x00100004, "xF4x80x80x84" },
  698.   { 0x00100008, "xF4x80x80x88" },
  699.   { 0x00100010, "xF4x80x80x90" },
  700.   { 0x00100020, "xF4x80x80xA0" },
  701.   { 0x00100040, "xF4x80x81x80" },
  702.   { 0x00100080, "xF4x80x82x80" },
  703.   { 0x00100100, "xF4x80x84x80" },
  704.   { 0x00100200, "xF4x80x88x80" },
  705.   { 0x00100400, "xF4x80x90x80" },
  706.   { 0x00100800, "xF4x80xA0x80" },
  707.   { 0x00101000, "xF4x81x80x80" },
  708.   { 0x00102000, "xF4x82x80x80" },
  709.   { 0x00104000, "xF4x84x80x80" },
  710.   { 0x00108000, "xF4x88x80x80" },
  711.   { 0x00110000, "xF4x90x80x80" },
  712.   { 0x00120000, "xF4xA0x80x80" },
  713.   { 0x00140000, "xF5x80x80x80" },
  714.   { 0x00180000, "xF6x80x80x80" },
  715.   { 0x001FFFFF, "xF7xBFxBFxBF" },
  716.           
  717.   { 0x00200000, "xF8x88x80x80x80" },
  718.   { 0x00200001, "xF8x88x80x80x81" },
  719.   { 0x00200002, "xF8x88x80x80x82" },
  720.   { 0x00200004, "xF8x88x80x80x84" },
  721.   { 0x00200008, "xF8x88x80x80x88" },
  722.   { 0x00200010, "xF8x88x80x80x90" },
  723.   { 0x00200020, "xF8x88x80x80xA0" },
  724.   { 0x00200040, "xF8x88x80x81x80" },
  725.   { 0x00200080, "xF8x88x80x82x80" },
  726.   { 0x00200100, "xF8x88x80x84x80" },
  727.   { 0x00200200, "xF8x88x80x88x80" },
  728.   { 0x00200400, "xF8x88x80x90x80" },
  729.   { 0x00200800, "xF8x88x80xA0x80" },
  730.   { 0x00201000, "xF8x88x81x80x80" },
  731.   { 0x00202000, "xF8x88x82x80x80" },
  732.   { 0x00204000, "xF8x88x84x80x80" },
  733.   { 0x00208000, "xF8x88x88x80x80" },
  734.   { 0x00210000, "xF8x88x90x80x80" },
  735.   { 0x00220000, "xF8x88xA0x80x80" },
  736.   { 0x00240000, "xF8x89x80x80x80" },
  737.   { 0x00280000, "xF8x8Ax80x80x80" },
  738.   { 0x00300000, "xF8x8Cx80x80x80" },
  739.   { 0x003FFFFF, "xF8x8FxBFxBFxBF" },
  740.   { 0x00400000, "xF8x90x80x80x80" },
  741.   { 0x00400001, "xF8x90x80x80x81" },
  742.   { 0x00400002, "xF8x90x80x80x82" },
  743.   { 0x00400004, "xF8x90x80x80x84" },
  744.   { 0x00400008, "xF8x90x80x80x88" },
  745.   { 0x00400010, "xF8x90x80x80x90" },
  746.   { 0x00400020, "xF8x90x80x80xA0" },
  747.   { 0x00400040, "xF8x90x80x81x80" },
  748.   { 0x00400080, "xF8x90x80x82x80" },
  749.   { 0x00400100, "xF8x90x80x84x80" },
  750.   { 0x00400200, "xF8x90x80x88x80" },
  751.   { 0x00400400, "xF8x90x80x90x80" },
  752.   { 0x00400800, "xF8x90x80xA0x80" },
  753.   { 0x00401000, "xF8x90x81x80x80" },
  754.   { 0x00402000, "xF8x90x82x80x80" },
  755.   { 0x00404000, "xF8x90x84x80x80" },
  756.   { 0x00408000, "xF8x90x88x80x80" },
  757.   { 0x00410000, "xF8x90x90x80x80" },
  758.   { 0x00420000, "xF8x90xA0x80x80" },
  759.   { 0x00440000, "xF8x91x80x80x80" },
  760.   { 0x00480000, "xF8x92x80x80x80" },
  761.   { 0x00500000, "xF8x94x80x80x80" },
  762.   { 0x00600000, "xF8x98x80x80x80" },
  763.   { 0x007FFFFF, "xF8x9FxBFxBFxBF" },
  764.   { 0x00800000, "xF8xA0x80x80x80" },
  765.   { 0x00800001, "xF8xA0x80x80x81" },
  766.   { 0x00800002, "xF8xA0x80x80x82" },
  767.   { 0x00800004, "xF8xA0x80x80x84" },
  768.   { 0x00800008, "xF8xA0x80x80x88" },
  769.   { 0x00800010, "xF8xA0x80x80x90" },
  770.   { 0x00800020, "xF8xA0x80x80xA0" },
  771.   { 0x00800040, "xF8xA0x80x81x80" },
  772.   { 0x00800080, "xF8xA0x80x82x80" },
  773.   { 0x00800100, "xF8xA0x80x84x80" },
  774.   { 0x00800200, "xF8xA0x80x88x80" },
  775.   { 0x00800400, "xF8xA0x80x90x80" },
  776.   { 0x00800800, "xF8xA0x80xA0x80" },
  777.   { 0x00801000, "xF8xA0x81x80x80" },
  778.   { 0x00802000, "xF8xA0x82x80x80" },
  779.   { 0x00804000, "xF8xA0x84x80x80" },
  780.   { 0x00808000, "xF8xA0x88x80x80" },
  781.   { 0x00810000, "xF8xA0x90x80x80" },
  782.   { 0x00820000, "xF8xA0xA0x80x80" },
  783.   { 0x00840000, "xF8xA1x80x80x80" },
  784.   { 0x00880000, "xF8xA2x80x80x80" },
  785.   { 0x00900000, "xF8xA4x80x80x80" },
  786.   { 0x00A00000, "xF8xA8x80x80x80" },
  787.   { 0x00C00000, "xF8xB0x80x80x80" },
  788.   { 0x00FFFFFF, "xF8xBFxBFxBFxBF" },
  789.   { 0x01000000, "xF9x80x80x80x80" },
  790.   { 0x01000001, "xF9x80x80x80x81" },
  791.   { 0x01000002, "xF9x80x80x80x82" },
  792.   { 0x01000004, "xF9x80x80x80x84" },
  793.   { 0x01000008, "xF9x80x80x80x88" },
  794.   { 0x01000010, "xF9x80x80x80x90" },
  795.   { 0x01000020, "xF9x80x80x80xA0" },
  796.   { 0x01000040, "xF9x80x80x81x80" },
  797.   { 0x01000080, "xF9x80x80x82x80" },
  798.   { 0x01000100, "xF9x80x80x84x80" },
  799.   { 0x01000200, "xF9x80x80x88x80" },
  800.   { 0x01000400, "xF9x80x80x90x80" },
  801.   { 0x01000800, "xF9x80x80xA0x80" },
  802.   { 0x01001000, "xF9x80x81x80x80" },
  803.   { 0x01002000, "xF9x80x82x80x80" },
  804.   { 0x01004000, "xF9x80x84x80x80" },
  805.   { 0x01008000, "xF9x80x88x80x80" },
  806.   { 0x01010000, "xF9x80x90x80x80" },
  807.   { 0x01020000, "xF9x80xA0x80x80" },
  808.   { 0x01040000, "xF9x81x80x80x80" },
  809.   { 0x01080000, "xF9x82x80x80x80" },
  810.   { 0x01100000, "xF9x84x80x80x80" },
  811.   { 0x01200000, "xF9x88x80x80x80" },
  812.   { 0x01400000, "xF9x90x80x80x80" },
  813.   { 0x01800000, "xF9xA0x80x80x80" },
  814.   { 0x01FFFFFF, "xF9xBFxBFxBFxBF" },
  815.   { 0x02000000, "xFAx80x80x80x80" },
  816.   { 0x02000001, "xFAx80x80x80x81" },
  817.   { 0x02000002, "xFAx80x80x80x82" },
  818.   { 0x02000004, "xFAx80x80x80x84" },
  819.   { 0x02000008, "xFAx80x80x80x88" },
  820.   { 0x02000010, "xFAx80x80x80x90" },
  821.   { 0x02000020, "xFAx80x80x80xA0" },
  822.   { 0x02000040, "xFAx80x80x81x80" },
  823.   { 0x02000080, "xFAx80x80x82x80" },
  824.   { 0x02000100, "xFAx80x80x84x80" },
  825.   { 0x02000200, "xFAx80x80x88x80" },
  826.   { 0x02000400, "xFAx80x80x90x80" },
  827.   { 0x02000800, "xFAx80x80xA0x80" },
  828.   { 0x02001000, "xFAx80x81x80x80" },
  829.   { 0x02002000, "xFAx80x82x80x80" },
  830.   { 0x02004000, "xFAx80x84x80x80" },
  831.   { 0x02008000, "xFAx80x88x80x80" },
  832.   { 0x02010000, "xFAx80x90x80x80" },
  833.   { 0x02020000, "xFAx80xA0x80x80" },
  834.   { 0x02040000, "xFAx81x80x80x80" },
  835.   { 0x02080000, "xFAx82x80x80x80" },
  836.   { 0x02100000, "xFAx84x80x80x80" },
  837.   { 0x02200000, "xFAx88x80x80x80" },
  838.   { 0x02400000, "xFAx90x80x80x80" },
  839.   { 0x02800000, "xFAxA0x80x80x80" },
  840.   { 0x03000000, "xFBx80x80x80x80" },
  841.   { 0x03FFFFFF, "xFBxBFxBFxBFxBF" },
  842.           
  843.   { 0x04000000, "xFCx84x80x80x80x80" },
  844.   { 0x04000001, "xFCx84x80x80x80x81" },
  845.   { 0x04000002, "xFCx84x80x80x80x82" },
  846.   { 0x04000004, "xFCx84x80x80x80x84" },
  847.   { 0x04000008, "xFCx84x80x80x80x88" },
  848.   { 0x04000010, "xFCx84x80x80x80x90" },
  849.   { 0x04000020, "xFCx84x80x80x80xA0" },
  850.   { 0x04000040, "xFCx84x80x80x81x80" },
  851.   { 0x04000080, "xFCx84x80x80x82x80" },
  852.   { 0x04000100, "xFCx84x80x80x84x80" },
  853.   { 0x04000200, "xFCx84x80x80x88x80" },
  854.   { 0x04000400, "xFCx84x80x80x90x80" },
  855.   { 0x04000800, "xFCx84x80x80xA0x80" },
  856.   { 0x04001000, "xFCx84x80x81x80x80" },
  857.   { 0x04002000, "xFCx84x80x82x80x80" },
  858.   { 0x04004000, "xFCx84x80x84x80x80" },
  859.   { 0x04008000, "xFCx84x80x88x80x80" },
  860.   { 0x04010000, "xFCx84x80x90x80x80" },
  861.   { 0x04020000, "xFCx84x80xA0x80x80" },
  862.   { 0x04040000, "xFCx84x81x80x80x80" },
  863.   { 0x04080000, "xFCx84x82x80x80x80" },
  864.   { 0x04100000, "xFCx84x84x80x80x80" },
  865.   { 0x04200000, "xFCx84x88x80x80x80" },
  866.   { 0x04400000, "xFCx84x90x80x80x80" },
  867.   { 0x04800000, "xFCx84xA0x80x80x80" },
  868.   { 0x05000000, "xFCx85x80x80x80x80" },
  869.   { 0x06000000, "xFCx86x80x80x80x80" },
  870.   { 0x07FFFFFF, "xFCx87xBFxBFxBFxBF" },
  871.   { 0x08000000, "xFCx88x80x80x80x80" },
  872.   { 0x08000001, "xFCx88x80x80x80x81" },
  873.   { 0x08000002, "xFCx88x80x80x80x82" },
  874.   { 0x08000004, "xFCx88x80x80x80x84" },
  875.   { 0x08000008, "xFCx88x80x80x80x88" },
  876.   { 0x08000010, "xFCx88x80x80x80x90" },
  877.   { 0x08000020, "xFCx88x80x80x80xA0" },
  878.   { 0x08000040, "xFCx88x80x80x81x80" },
  879.   { 0x08000080, "xFCx88x80x80x82x80" },
  880.   { 0x08000100, "xFCx88x80x80x84x80" },
  881.   { 0x08000200, "xFCx88x80x80x88x80" },
  882.   { 0x08000400, "xFCx88x80x80x90x80" },
  883.   { 0x08000800, "xFCx88x80x80xA0x80" },
  884.   { 0x08001000, "xFCx88x80x81x80x80" },
  885.   { 0x08002000, "xFCx88x80x82x80x80" },
  886.   { 0x08004000, "xFCx88x80x84x80x80" },
  887.   { 0x08008000, "xFCx88x80x88x80x80" },
  888.   { 0x08010000, "xFCx88x80x90x80x80" },
  889.   { 0x08020000, "xFCx88x80xA0x80x80" },
  890.   { 0x08040000, "xFCx88x81x80x80x80" },
  891.   { 0x08080000, "xFCx88x82x80x80x80" },
  892.   { 0x08100000, "xFCx88x84x80x80x80" },
  893.   { 0x08200000, "xFCx88x88x80x80x80" },
  894.   { 0x08400000, "xFCx88x90x80x80x80" },
  895.   { 0x08800000, "xFCx88xA0x80x80x80" },
  896.   { 0x09000000, "xFCx89x80x80x80x80" },
  897.   { 0x0A000000, "xFCx8Ax80x80x80x80" },
  898.   { 0x0C000000, "xFCx8Cx80x80x80x80" },
  899.   { 0x0FFFFFFF, "xFCx8FxBFxBFxBFxBF" },
  900.   { 0x10000000, "xFCx90x80x80x80x80" },
  901.   { 0x10000001, "xFCx90x80x80x80x81" },
  902.   { 0x10000002, "xFCx90x80x80x80x82" },
  903.   { 0x10000004, "xFCx90x80x80x80x84" },
  904.   { 0x10000008, "xFCx90x80x80x80x88" },
  905.   { 0x10000010, "xFCx90x80x80x80x90" },
  906.   { 0x10000020, "xFCx90x80x80x80xA0" },
  907.   { 0x10000040, "xFCx90x80x80x81x80" },
  908.   { 0x10000080, "xFCx90x80x80x82x80" },
  909.   { 0x10000100, "xFCx90x80x80x84x80" },
  910.   { 0x10000200, "xFCx90x80x80x88x80" },
  911.   { 0x10000400, "xFCx90x80x80x90x80" },
  912.   { 0x10000800, "xFCx90x80x80xA0x80" },
  913.   { 0x10001000, "xFCx90x80x81x80x80" },
  914.   { 0x10002000, "xFCx90x80x82x80x80" },
  915.   { 0x10004000, "xFCx90x80x84x80x80" },
  916.   { 0x10008000, "xFCx90x80x88x80x80" },
  917.   { 0x10010000, "xFCx90x80x90x80x80" },
  918.   { 0x10020000, "xFCx90x80xA0x80x80" },
  919.   { 0x10040000, "xFCx90x81x80x80x80" },
  920.   { 0x10080000, "xFCx90x82x80x80x80" },
  921.   { 0x10100000, "xFCx90x84x80x80x80" },
  922.   { 0x10200000, "xFCx90x88x80x80x80" },
  923.   { 0x10400000, "xFCx90x90x80x80x80" },
  924.   { 0x10800000, "xFCx90xA0x80x80x80" },
  925.   { 0x11000000, "xFCx91x80x80x80x80" },
  926.   { 0x12000000, "xFCx92x80x80x80x80" },
  927.   { 0x14000000, "xFCx94x80x80x80x80" },
  928.   { 0x18000000, "xFCx98x80x80x80x80" },
  929.   { 0x1FFFFFFF, "xFCx9FxBFxBFxBFxBF" },
  930.   { 0x20000000, "xFCxA0x80x80x80x80" },
  931.   { 0x20000001, "xFCxA0x80x80x80x81" },
  932.   { 0x20000002, "xFCxA0x80x80x80x82" },
  933.   { 0x20000004, "xFCxA0x80x80x80x84" },
  934.   { 0x20000008, "xFCxA0x80x80x80x88" },
  935.   { 0x20000010, "xFCxA0x80x80x80x90" },
  936.   { 0x20000020, "xFCxA0x80x80x80xA0" },
  937.   { 0x20000040, "xFCxA0x80x80x81x80" },
  938.   { 0x20000080, "xFCxA0x80x80x82x80" },
  939.   { 0x20000100, "xFCxA0x80x80x84x80" },
  940.   { 0x20000200, "xFCxA0x80x80x88x80" },
  941.   { 0x20000400, "xFCxA0x80x80x90x80" },
  942.   { 0x20000800, "xFCxA0x80x80xA0x80" },
  943.   { 0x20001000, "xFCxA0x80x81x80x80" },
  944.   { 0x20002000, "xFCxA0x80x82x80x80" },
  945.   { 0x20004000, "xFCxA0x80x84x80x80" },
  946.   { 0x20008000, "xFCxA0x80x88x80x80" },
  947.   { 0x20010000, "xFCxA0x80x90x80x80" },
  948.   { 0x20020000, "xFCxA0x80xA0x80x80" },
  949.   { 0x20040000, "xFCxA0x81x80x80x80" },
  950.   { 0x20080000, "xFCxA0x82x80x80x80" },
  951.   { 0x20100000, "xFCxA0x84x80x80x80" },
  952.   { 0x20200000, "xFCxA0x88x80x80x80" },
  953.   { 0x20400000, "xFCxA0x90x80x80x80" },
  954.   { 0x20800000, "xFCxA0xA0x80x80x80" },
  955.   { 0x21000000, "xFCxA1x80x80x80x80" },
  956.   { 0x22000000, "xFCxA2x80x80x80x80" },
  957.   { 0x24000000, "xFCxA4x80x80x80x80" },
  958.   { 0x28000000, "xFCxA8x80x80x80x80" },
  959.   { 0x30000000, "xFCxB0x80x80x80x80" },
  960.   { 0x3FFFFFFF, "xFCxBFxBFxBFxBFxBF" },
  961.   { 0x40000000, "xFDx80x80x80x80x80" },
  962.   { 0x40000001, "xFDx80x80x80x80x81" },
  963.   { 0x40000002, "xFDx80x80x80x80x82" },
  964.   { 0x40000004, "xFDx80x80x80x80x84" },
  965.   { 0x40000008, "xFDx80x80x80x80x88" },
  966.   { 0x40000010, "xFDx80x80x80x80x90" },
  967.   { 0x40000020, "xFDx80x80x80x80xA0" },
  968.   { 0x40000040, "xFDx80x80x80x81x80" },
  969.   { 0x40000080, "xFDx80x80x80x82x80" },
  970.   { 0x40000100, "xFDx80x80x80x84x80" },
  971.   { 0x40000200, "xFDx80x80x80x88x80" },
  972.   { 0x40000400, "xFDx80x80x80x90x80" },
  973.   { 0x40000800, "xFDx80x80x80xA0x80" },
  974.   { 0x40001000, "xFDx80x80x81x80x80" },
  975.   { 0x40002000, "xFDx80x80x82x80x80" },
  976.   { 0x40004000, "xFDx80x80x84x80x80" },
  977.   { 0x40008000, "xFDx80x80x88x80x80" },
  978.   { 0x40010000, "xFDx80x80x90x80x80" },
  979.   { 0x40020000, "xFDx80x80xA0x80x80" },
  980.   { 0x40040000, "xFDx80x81x80x80x80" },
  981.   { 0x40080000, "xFDx80x82x80x80x80" },
  982.   { 0x40100000, "xFDx80x84x80x80x80" },
  983.   { 0x40200000, "xFDx80x88x80x80x80" },
  984.   { 0x40400000, "xFDx80x90x80x80x80" },
  985.   { 0x40800000, "xFDx80xA0x80x80x80" },
  986.   { 0x41000000, "xFDx81x80x80x80x80" },
  987.   { 0x42000000, "xFDx82x80x80x80x80" },
  988.   { 0x44000000, "xFDx84x80x80x80x80" },
  989.   { 0x48000000, "xFDx88x80x80x80x80" },
  990.   { 0x50000000, "xFDx90x80x80x80x80" },
  991.   { 0x60000000, "xFDxA0x80x80x80x80" },
  992.   { 0x7FFFFFFF, "xFDxBFxBFxBFxBFxBF" }
  993. };
  994. /*
  995.  * UCS-2 vectors
  996.  */
  997. struct ucs2 ucs2[] = {
  998.   { 0x0001, "x01" },
  999.   { 0x0002, "x02" },
  1000.   { 0x0003, "x03" },
  1001.   { 0x0004, "x04" },
  1002.   { 0x0007, "x07" },
  1003.   { 0x0008, "x08" },
  1004.   { 0x000F, "x0F" },
  1005.   { 0x0010, "x10" },
  1006.   { 0x001F, "x1F" },
  1007.   { 0x0020, "x20" },
  1008.   { 0x003F, "x3F" },
  1009.   { 0x0040, "x40" },
  1010.   { 0x007F, "x7F" },
  1011.           
  1012.   { 0x0080, "xC2x80" },
  1013.   { 0x0081, "xC2x81" },
  1014.   { 0x0082, "xC2x82" },
  1015.   { 0x0084, "xC2x84" },
  1016.   { 0x0088, "xC2x88" },
  1017.   { 0x0090, "xC2x90" },
  1018.   { 0x00A0, "xC2xA0" },
  1019.   { 0x00C0, "xC3x80" },
  1020.   { 0x00FF, "xC3xBF" },
  1021.   { 0x0100, "xC4x80" },
  1022.   { 0x0101, "xC4x81" },
  1023.   { 0x0102, "xC4x82" },
  1024.   { 0x0104, "xC4x84" },
  1025.   { 0x0108, "xC4x88" },
  1026.   { 0x0110, "xC4x90" },
  1027.   { 0x0120, "xC4xA0" },
  1028.   { 0x0140, "xC5x80" },
  1029.   { 0x0180, "xC6x80" },
  1030.   { 0x01FF, "xC7xBF" },
  1031.   { 0x0200, "xC8x80" },
  1032.   { 0x0201, "xC8x81" },
  1033.   { 0x0202, "xC8x82" },
  1034.   { 0x0204, "xC8x84" },
  1035.   { 0x0208, "xC8x88" },
  1036.   { 0x0210, "xC8x90" },
  1037.   { 0x0220, "xC8xA0" },
  1038.   { 0x0240, "xC9x80" },
  1039.   { 0x0280, "xCAx80" },
  1040.   { 0x0300, "xCCx80" },
  1041.   { 0x03FF, "xCFxBF" },
  1042.   { 0x0400, "xD0x80" },
  1043.   { 0x0401, "xD0x81" },
  1044.   { 0x0402, "xD0x82" },
  1045.   { 0x0404, "xD0x84" },
  1046.   { 0x0408, "xD0x88" },
  1047.   { 0x0410, "xD0x90" },
  1048.   { 0x0420, "xD0xA0" },
  1049.   { 0x0440, "xD1x80" },
  1050.   { 0x0480, "xD2x80" },
  1051.   { 0x0500, "xD4x80" },
  1052.   { 0x0600, "xD8x80" },
  1053.   { 0x07FF, "xDFxBF" },
  1054.           
  1055.   { 0x0800, "xE0xA0x80" },
  1056.   { 0x0801, "xE0xA0x81" },
  1057.   { 0x0802, "xE0xA0x82" },
  1058.   { 0x0804, "xE0xA0x84" },
  1059.   { 0x0808, "xE0xA0x88" },
  1060.   { 0x0810, "xE0xA0x90" },
  1061.   { 0x0820, "xE0xA0xA0" },
  1062.   { 0x0840, "xE0xA1x80" },
  1063.   { 0x0880, "xE0xA2x80" },
  1064.   { 0x0900, "xE0xA4x80" },
  1065.   { 0x0A00, "xE0xA8x80" },
  1066.   { 0x0C00, "xE0xB0x80" },
  1067.   { 0x0FFF, "xE0xBFxBF" },
  1068.   { 0x1000, "xE1x80x80" },
  1069.   { 0x1001, "xE1x80x81" },
  1070.   { 0x1002, "xE1x80x82" },
  1071.   { 0x1004, "xE1x80x84" },
  1072.   { 0x1008, "xE1x80x88" },
  1073.   { 0x1010, "xE1x80x90" },
  1074.   { 0x1020, "xE1x80xA0" },
  1075.   { 0x1040, "xE1x81x80" },
  1076.   { 0x1080, "xE1x82x80" },
  1077.   { 0x1100, "xE1x84x80" },
  1078.   { 0x1200, "xE1x88x80" },
  1079.   { 0x1400, "xE1x90x80" },
  1080.   { 0x1800, "xE1xA0x80" },
  1081.   { 0x1FFF, "xE1xBFxBF" },
  1082.   { 0x2000, "xE2x80x80" },
  1083.   { 0x2001, "xE2x80x81" },
  1084.   { 0x2002, "xE2x80x82" },
  1085.   { 0x2004, "xE2x80x84" },
  1086.   { 0x2008, "xE2x80x88" },
  1087.   { 0x2010, "xE2x80x90" },
  1088.   { 0x2020, "xE2x80xA0" },
  1089.   { 0x2040, "xE2x81x80" },
  1090.   { 0x2080, "xE2x82x80" },
  1091.   { 0x2100, "xE2x84x80" },
  1092.   { 0x2200, "xE2x88x80" },
  1093.   { 0x2400, "xE2x90x80" },
  1094.   { 0x2800, "xE2xA0x80" },
  1095.   { 0x3000, "xE3x80x80" },
  1096.   { 0x3FFF, "xE3xBFxBF" },
  1097.   { 0x4000, "xE4x80x80" },
  1098.   { 0x4001, "xE4x80x81" },
  1099.   { 0x4002, "xE4x80x82" },
  1100.   { 0x4004, "xE4x80x84" },
  1101.   { 0x4008, "xE4x80x88" },
  1102.   { 0x4010, "xE4x80x90" },
  1103.   { 0x4020, "xE4x80xA0" },
  1104.   { 0x4040, "xE4x81x80" },
  1105.   { 0x4080, "xE4x82x80" },
  1106.   { 0x4100, "xE4x84x80" },
  1107.   { 0x4200, "xE4x88x80" },
  1108.   { 0x4400, "xE4x90x80" },
  1109.   { 0x4800, "xE4xA0x80" },
  1110.   { 0x5000, "xE5x80x80" },
  1111.   { 0x6000, "xE6x80x80" },
  1112.   { 0x7FFF, "xE7xBFxBF" },
  1113.   { 0x8000, "xE8x80x80" },
  1114.   { 0x8001, "xE8x80x81" },
  1115.   { 0x8002, "xE8x80x82" },
  1116.   { 0x8004, "xE8x80x84" },
  1117.   { 0x8008, "xE8x80x88" },
  1118.   { 0x8010, "xE8x80x90" },
  1119.   { 0x8020, "xE8x80xA0" },
  1120.   { 0x8040, "xE8x81x80" },
  1121.   { 0x8080, "xE8x82x80" },
  1122.   { 0x8100, "xE8x84x80" },
  1123.   { 0x8200, "xE8x88x80" },
  1124.   { 0x8400, "xE8x90x80" },
  1125.   { 0x8800, "xE8xA0x80" },
  1126.   { 0x9000, "xE9x80x80" },
  1127.   { 0xA000, "xEAx80x80" },
  1128.   { 0xC000, "xECx80x80" },
  1129.   { 0xFFFF, "xEFxBFxBF" }
  1130. };
  1131. #ifdef UTF16
  1132. /*
  1133.  * UTF-16 vectors
  1134.  */
  1135. struct utf16 utf16[] = {
  1136.   { 0x00010000, { 0xD800, 0xDC00 } },
  1137.   { 0x00010001, { 0xD800, 0xDC01 } },
  1138.   { 0x00010002, { 0xD800, 0xDC02 } },
  1139.   { 0x00010003, { 0xD800, 0xDC03 } },
  1140.   { 0x00010004, { 0xD800, 0xDC04 } },
  1141.   { 0x00010007, { 0xD800, 0xDC07 } },
  1142.   { 0x00010008, { 0xD800, 0xDC08 } },
  1143.   { 0x0001000F, { 0xD800, 0xDC0F } },
  1144.   { 0x00010010, { 0xD800, 0xDC10 } },
  1145.   { 0x0001001F, { 0xD800, 0xDC1F } },
  1146.   { 0x00010020, { 0xD800, 0xDC20 } },
  1147.   { 0x0001003F, { 0xD800, 0xDC3F } },
  1148.   { 0x00010040, { 0xD800, 0xDC40 } },
  1149.   { 0x0001007F, { 0xD800, 0xDC7F } },
  1150.   { 0x00010080, { 0xD800, 0xDC80 } },
  1151.   { 0x00010081, { 0xD800, 0xDC81 } },
  1152.   { 0x00010082, { 0xD800, 0xDC82 } },
  1153.   { 0x00010084, { 0xD800, 0xDC84 } },
  1154.   { 0x00010088, { 0xD800, 0xDC88 } },
  1155.   { 0x00010090, { 0xD800, 0xDC90 } },
  1156.   { 0x000100A0, { 0xD800, 0xDCA0 } },
  1157.   { 0x000100C0, { 0xD800, 0xDCC0 } },
  1158.   { 0x000100FF, { 0xD800, 0xDCFF } },
  1159.   { 0x00010100, { 0xD800, 0xDD00 } },
  1160.   { 0x00010101, { 0xD800, 0xDD01 } },
  1161.   { 0x00010102, { 0xD800, 0xDD02 } },
  1162.   { 0x00010104, { 0xD800, 0xDD04 } },
  1163.   { 0x00010108, { 0xD800, 0xDD08 } },
  1164.   { 0x00010110, { 0xD800, 0xDD10 } },
  1165.   { 0x00010120, { 0xD800, 0xDD20 } },
  1166.   { 0x00010140, { 0xD800, 0xDD40 } },
  1167.   { 0x00010180, { 0xD800, 0xDD80 } },
  1168.   { 0x000101FF, { 0xD800, 0xDDFF } },
  1169.   { 0x00010200, { 0xD800, 0xDE00 } },
  1170.   { 0x00010201, { 0xD800, 0xDE01 } },
  1171.   { 0x00010202, { 0xD800, 0xDE02 } },
  1172.   { 0x00010204, { 0xD800, 0xDE04 } },
  1173.   { 0x00010208, { 0xD800, 0xDE08 } },
  1174.   { 0x00010210, { 0xD800, 0xDE10 } },
  1175.   { 0x00010220, { 0xD800, 0xDE20 } },
  1176.   { 0x00010240, { 0xD800, 0xDE40 } },
  1177.   { 0x00010280, { 0xD800, 0xDE80 } },
  1178.   { 0x00010300, { 0xD800, 0xDF00 } },
  1179.   { 0x000103FF, { 0xD800, 0xDFFF } },
  1180.   { 0x00010400, { 0xD801, 0xDC00 } },
  1181.   { 0x00010401, { 0xD801, 0xDC01 } },
  1182.   { 0x00010402, { 0xD801, 0xDC02 } },
  1183.   { 0x00010404, { 0xD801, 0xDC04 } },
  1184.   { 0x00010408, { 0xD801, 0xDC08 } },
  1185.   { 0x00010410, { 0xD801, 0xDC10 } },
  1186.   { 0x00010420, { 0xD801, 0xDC20 } },
  1187.   { 0x00010440, { 0xD801, 0xDC40 } },
  1188.   { 0x00010480, { 0xD801, 0xDC80 } },
  1189.   { 0x00010500, { 0xD801, 0xDD00 } },
  1190.   { 0x00010600, { 0xD801, 0xDE00 } },
  1191.   { 0x000107FF, { 0xD801, 0xDFFF } },
  1192.   { 0x00010800, { 0xD802, 0xDC00 } },
  1193.   { 0x00010801, { 0xD802, 0xDC01 } },
  1194.   { 0x00010802, { 0xD802, 0xDC02 } },
  1195.   { 0x00010804, { 0xD802, 0xDC04 } },
  1196.   { 0x00010808, { 0xD802, 0xDC08 } },
  1197.   { 0x00010810, { 0xD802, 0xDC10 } },
  1198.   { 0x00010820, { 0xD802, 0xDC20 } },
  1199.   { 0x00010840, { 0xD802, 0xDC40 } },
  1200.   { 0x00010880, { 0xD802, 0xDC80 } },
  1201.   { 0x00010900, { 0xD802, 0xDD00 } },
  1202.   { 0x00010A00, { 0xD802, 0xDE00 } },
  1203.   { 0x00010C00, { 0xD803, 0xDC00 } },
  1204.   { 0x00010FFF, { 0xD803, 0xDFFF } },
  1205.   { 0x00011000, { 0xD804, 0xDC00 } },
  1206.   { 0x00011001, { 0xD804, 0xDC01 } },
  1207.   { 0x00011002, { 0xD804, 0xDC02 } },
  1208.   { 0x00011004, { 0xD804, 0xDC04 } },
  1209.   { 0x00011008, { 0xD804, 0xDC08 } },
  1210.   { 0x00011010, { 0xD804, 0xDC10 } },
  1211.   { 0x00011020, { 0xD804, 0xDC20 } },
  1212.   { 0x00011040, { 0xD804, 0xDC40 } },
  1213.   { 0x00011080, { 0xD804, 0xDC80 } },
  1214.   { 0x00011100, { 0xD804, 0xDD00 } },
  1215.   { 0x00011200, { 0xD804, 0xDE00 } },
  1216.   { 0x00011400, { 0xD805, 0xDC00 } },
  1217.   { 0x00011800, { 0xD806, 0xDC00 } },
  1218.   { 0x00011FFF, { 0xD807, 0xDFFF } },
  1219.   { 0x00012000, { 0xD808, 0xDC00 } },
  1220.   { 0x00012001, { 0xD808, 0xDC01 } },
  1221.   { 0x00012002, { 0xD808, 0xDC02 } },
  1222.   { 0x00012004, { 0xD808, 0xDC04 } },
  1223.   { 0x00012008, { 0xD808, 0xDC08 } },
  1224.   { 0x00012010, { 0xD808, 0xDC10 } },
  1225.   { 0x00012020, { 0xD808, 0xDC20 } },
  1226.   { 0x00012040, { 0xD808, 0xDC40 } },
  1227.   { 0x00012080, { 0xD808, 0xDC80 } },
  1228.   { 0x00012100, { 0xD808, 0xDD00 } },
  1229.   { 0x00012200, { 0xD808, 0xDE00 } },
  1230.   { 0x00012400, { 0xD809, 0xDC00 } },
  1231.   { 0x00012800, { 0xD80A, 0xDC00 } },
  1232.   { 0x00013000, { 0xD80C, 0xDC00 } },
  1233.   { 0x00013FFF, { 0xD80F, 0xDFFF } },
  1234.   { 0x00014000, { 0xD810, 0xDC00 } },
  1235.   { 0x00014001, { 0xD810, 0xDC01 } },
  1236.   { 0x00014002, { 0xD810, 0xDC02 } },
  1237.   { 0x00014004, { 0xD810, 0xDC04 } },
  1238.   { 0x00014008, { 0xD810, 0xDC08 } },
  1239.   { 0x00014010, { 0xD810, 0xDC10 } },
  1240.   { 0x00014020, { 0xD810, 0xDC20 } },
  1241.   { 0x00014040, { 0xD810, 0xDC40 } },
  1242.   { 0x00014080, { 0xD810, 0xDC80 } },
  1243.   { 0x00014100, { 0xD810, 0xDD00 } },
  1244.   { 0x00014200, { 0xD810, 0xDE00 } },
  1245.   { 0x00014400, { 0xD811, 0xDC00 } },
  1246.   { 0x00014800, { 0xD812, 0xDC00 } },
  1247.   { 0x00015000, { 0xD814, 0xDC00 } },
  1248.   { 0x00016000, { 0xD818, 0xDC00 } },
  1249.   { 0x00017FFF, { 0xD81F, 0xDFFF } },
  1250.   { 0x00018000, { 0xD820, 0xDC00 } },
  1251.   { 0x00018001, { 0xD820, 0xDC01 } },
  1252.   { 0x00018002, { 0xD820, 0xDC02 } },
  1253.   { 0x00018004, { 0xD820, 0xDC04 } },
  1254.   { 0x00018008, { 0xD820, 0xDC08 } },
  1255.   { 0x00018010, { 0xD820, 0xDC10 } },
  1256.   { 0x00018020, { 0xD820, 0xDC20 } },
  1257.   { 0x00018040, { 0xD820, 0xDC40 } },
  1258.   { 0x00018080, { 0xD820, 0xDC80 } },
  1259.   { 0x00018100, { 0xD820, 0xDD00 } },
  1260.   { 0x00018200, { 0xD820, 0xDE00 } },
  1261.   { 0x00018400, { 0xD821, 0xDC00 } },
  1262.   { 0x00018800, { 0xD822, 0xDC00 } },
  1263.   { 0x00019000, { 0xD824, 0xDC00 } },
  1264.   { 0x0001A000, { 0xD828, 0xDC00 } },
  1265.   { 0x0001C000, { 0xD830, 0xDC00 } },
  1266.   { 0x0001FFFF, { 0xD83F, 0xDFFF } },
  1267.   { 0x00020000, { 0xD840, 0xDC00 } },
  1268.   { 0x00020001, { 0xD840, 0xDC01 } },
  1269.   { 0x00020002, { 0xD840, 0xDC02 } },
  1270.   { 0x00020004, { 0xD840, 0xDC04 } },
  1271.   { 0x00020008, { 0xD840, 0xDC08 } },
  1272.   { 0x00020010, { 0xD840, 0xDC10 } },
  1273.   { 0x00020020, { 0xD840, 0xDC20 } },
  1274.   { 0x00020040, { 0xD840, 0xDC40 } },
  1275.   { 0x00020080, { 0xD840, 0xDC80 } },
  1276.   { 0x00020100, { 0xD840, 0xDD00 } },
  1277.   { 0x00020200, { 0xD840, 0xDE00 } },
  1278.   { 0x00020400, { 0xD841, 0xDC00 } },
  1279.   { 0x00020800, { 0xD842, 0xDC00 } },
  1280.   { 0x00021000, { 0xD844, 0xDC00 } },
  1281.   { 0x00022000, { 0xD848, 0xDC00 } },
  1282.   { 0x00024000, { 0xD850, 0xDC00 } },
  1283.   { 0x00028000, { 0xD860, 0xDC00 } },
  1284.   { 0x0002FFFF, { 0xD87F, 0xDFFF } },
  1285.   { 0x00030000, { 0xD880, 0xDC00 } },
  1286.   { 0x00030001, { 0xD880, 0xDC01 } },
  1287.   { 0x00030002, { 0xD880, 0xDC02 } },
  1288.   { 0x00030004, { 0xD880, 0xDC04 } },
  1289.   { 0x00030008, { 0xD880, 0xDC08 } },
  1290.   { 0x00030010, { 0xD880, 0xDC10 } },
  1291.   { 0x00030020, { 0xD880, 0xDC20 } },
  1292.   { 0x00030040, { 0xD880, 0xDC40 } },
  1293.   { 0x00030080, { 0xD880, 0xDC80 } },
  1294.   { 0x00030100, { 0xD880, 0xDD00 } },
  1295.   { 0x00030200, { 0xD880, 0xDE00 } },
  1296.   { 0x00030400, { 0xD881, 0xDC00 } },
  1297.   { 0x00030800, { 0xD882, 0xDC00 } },
  1298.   { 0x00031000, { 0xD884, 0xDC00 } },
  1299.   { 0x00032000, { 0xD888, 0xDC00 } },
  1300.   { 0x00034000, { 0xD890, 0xDC00 } },
  1301.   { 0x00038000, { 0xD8A0, 0xDC00 } },
  1302.   { 0x0003FFFF, { 0xD8BF, 0xDFFF } },
  1303.   { 0x00040000, { 0xD8C0, 0xDC00 } },
  1304.   { 0x00040001, { 0xD8C0, 0xDC01 } },
  1305.   { 0x00040002, { 0xD8C0, 0xDC02 } },
  1306.   { 0x00040004, { 0xD8C0, 0xDC04 } },
  1307.   { 0x00040008, { 0xD8C0, 0xDC08 } },
  1308.   { 0x00040010, { 0xD8C0, 0xDC10 } },
  1309.   { 0x00040020, { 0xD8C0, 0xDC20 } },
  1310.   { 0x00040040, { 0xD8C0, 0xDC40 } },
  1311.   { 0x00040080, { 0xD8C0, 0xDC80 } },
  1312.   { 0x00040100, { 0xD8C0, 0xDD00 } },
  1313.   { 0x00040200, { 0xD8C0, 0xDE00 } },
  1314.   { 0x00040400, { 0xD8C1, 0xDC00 } },
  1315.   { 0x00040800, { 0xD8C2, 0xDC00 } },
  1316.   { 0x00041000, { 0xD8C4, 0xDC00 } },
  1317.   { 0x00042000, { 0xD8C8, 0xDC00 } },
  1318.   { 0x00044000, { 0xD8D0, 0xDC00 } },
  1319.   { 0x00048000, { 0xD8E0, 0xDC00 } },
  1320.   { 0x0004FFFF, { 0xD8FF, 0xDFFF } },
  1321.   { 0x00050000, { 0xD900, 0xDC00 } },
  1322.   { 0x00050001, { 0xD900, 0xDC01 } },
  1323.   { 0x00050002, { 0xD900, 0xDC02 } },
  1324.   { 0x00050004, { 0xD900, 0xDC04 } },
  1325.   { 0x00050008, { 0xD900, 0xDC08 } },
  1326.   { 0x00050010, { 0xD900, 0xDC10 } },
  1327.   { 0x00050020, { 0xD900, 0xDC20 } },
  1328.   { 0x00050040, { 0xD900, 0xDC40 } },
  1329.   { 0x00050080, { 0xD900, 0xDC80 } },
  1330.   { 0x00050100, { 0xD900, 0xDD00 } },
  1331.   { 0x00050200, { 0xD900, 0xDE00 } },
  1332.   { 0x00050400, { 0xD901, 0xDC00 } },
  1333.   { 0x00050800, { 0xD902, 0xDC00 } },
  1334.   { 0x00051000, { 0xD904, 0xDC00 } },
  1335.   { 0x00052000, { 0xD908, 0xDC00 } },
  1336.   { 0x00054000, { 0xD910, 0xDC00 } },
  1337.   { 0x00058000, { 0xD920, 0xDC00 } },
  1338.   { 0x00060000, { 0xD940, 0xDC00 } },
  1339.   { 0x00070000, { 0xD980, 0xDC00 } },
  1340.   { 0x0007FFFF, { 0xD9BF, 0xDFFF } },
  1341.   { 0x00080000, { 0xD9C0, 0xDC00 } },
  1342.   { 0x00080001, { 0xD9C0, 0xDC01 } },
  1343.   { 0x00080002, { 0xD9C0, 0xDC02 } },
  1344.   { 0x00080004, { 0xD9C0, 0xDC04 } },
  1345.   { 0x00080008, { 0xD9C0, 0xDC08 } },
  1346.   { 0x00080010, { 0xD9C0, 0xDC10 } },
  1347.   { 0x00080020, { 0xD9C0, 0xDC20 } },
  1348.   { 0x00080040, { 0xD9C0, 0xDC40 } },
  1349.   { 0x00080080, { 0xD9C0, 0xDC80 } },
  1350.   { 0x00080100, { 0xD9C0, 0xDD00 } },
  1351.   { 0x00080200, { 0xD9C0, 0xDE00 } },
  1352.   { 0x00080400, { 0xD9C1, 0xDC00 } },
  1353.   { 0x00080800, { 0xD9C2, 0xDC00 } },
  1354.   { 0x00081000, { 0xD9C4, 0xDC00 } },
  1355.   { 0x00082000, { 0xD9C8, 0xDC00 } },
  1356.   { 0x00084000, { 0xD9D0, 0xDC00 } },
  1357.   { 0x00088000, { 0xD9E0, 0xDC00 } },
  1358.   { 0x0008FFFF, { 0xD9FF, 0xDFFF } },
  1359.   { 0x00090000, { 0xDA00, 0xDC00 } },
  1360.   { 0x00090001, { 0xDA00, 0xDC01 } },
  1361.   { 0x00090002, { 0xDA00, 0xDC02 } },
  1362.   { 0x00090004, { 0xDA00, 0xDC04 } },
  1363.   { 0x00090008, { 0xDA00, 0xDC08 } },
  1364.   { 0x00090010, { 0xDA00, 0xDC10 } },
  1365.   { 0x00090020, { 0xDA00, 0xDC20 } },
  1366.   { 0x00090040, { 0xDA00, 0xDC40 } },
  1367.   { 0x00090080, { 0xDA00, 0xDC80 } },
  1368.   { 0x00090100, { 0xDA00, 0xDD00 } },
  1369.   { 0x00090200, { 0xDA00, 0xDE00 } },
  1370.   { 0x00090400, { 0xDA01, 0xDC00 } },
  1371.   { 0x00090800, { 0xDA02, 0xDC00 } },
  1372.   { 0x00091000, { 0xDA04, 0xDC00 } },
  1373.   { 0x00092000, { 0xDA08, 0xDC00 } },
  1374.   { 0x00094000, { 0xDA10, 0xDC00 } },
  1375.   { 0x00098000, { 0xDA20, 0xDC00 } },
  1376.   { 0x000A0000, { 0xDA40, 0xDC00 } },
  1377.   { 0x000B0000, { 0xDA80, 0xDC00 } },
  1378.   { 0x000C0000, { 0xDAC0, 0xDC00 } },
  1379.   { 0x000D0000, { 0xDB00, 0xDC00 } },
  1380.   { 0x000FFFFF, { 0xDBBF, 0xDFFF } },
  1381.   { 0x0010FFFF, { 0xDBFF, 0xDFFF } }
  1382. };
  1383. #endif /* UTF16 */
  1384. static void
  1385. dump_utf8
  1386. (
  1387.   char *word,
  1388.   unsigned char *utf8,
  1389.   char *end
  1390. )
  1391. {
  1392.   fprintf(stdout, "%s ", word);
  1393.   for( ; *utf8; utf8++ ) {
  1394.     fprintf(stdout, "%02.2x ", (unsigned int)*utf8);
  1395.   }
  1396.   fprintf(stdout, "%s", end);
  1397. }
  1398. static PRBool
  1399. test_ucs4_chars
  1400. (
  1401.   void
  1402. )
  1403. {
  1404.   PRBool rv = PR_TRUE;
  1405.   int i;
  1406.   for( i = 0; i < sizeof(ucs4)/sizeof(ucs4[0]); i++ ) {
  1407.     struct ucs4 *e = &ucs4[i];
  1408.     PRBool result;
  1409.     unsigned char utf8[8];
  1410.     unsigned int len = 0;
  1411.     PRUint32 back = 0;
  1412.     (void)memset(utf8, 0, sizeof(utf8));
  1413.     
  1414.     result = sec_port_ucs4_utf8_conversion_function(PR_FALSE, 
  1415.       (unsigned char *)&e->c, sizeof(e->c), utf8, sizeof(utf8), &len);
  1416.     if( !result ) {
  1417.       fprintf(stdout, "Failed to convert UCS-4 0x%08.8x to UTF-8n", e->c);
  1418.       rv = PR_FALSE;
  1419.       continue;
  1420.     }
  1421.     if( (len >= sizeof(utf8)) ||
  1422.         (strlen(e->utf8) != len) ||
  1423.         (utf8[len] = '', 0 != strcmp(e->utf8, utf8)) ) {
  1424.       fprintf(stdout, "Wrong conversion of UCS-4 0x%08.8x to UTF-8: ", e->c);
  1425.       dump_utf8("expected", e->utf8, ", ");
  1426.       dump_utf8("received", utf8, "n");
  1427.       rv = PR_FALSE;
  1428.       continue;
  1429.     }
  1430.     result = sec_port_ucs4_utf8_conversion_function(PR_TRUE,
  1431.       utf8, len, (unsigned char *)&back, sizeof(back), &len);
  1432.     if( !result ) {
  1433.       dump_utf8("Failed to convert UTF-8", utf8, "to UCS-4n");
  1434.       rv = PR_FALSE;
  1435.       continue;
  1436.     }
  1437.     if( (sizeof(back) != len) || (e->c != back) ) {
  1438.       dump_utf8("Wrong conversion of UTF-8", utf8, " to UCS-4:");
  1439.       fprintf(stdout, "expected 0x%08.8x, received 0x%08.8xn", e->c, back);
  1440.       rv = PR_FALSE;
  1441.       continue;
  1442.     }
  1443.   }
  1444.   return rv;
  1445. }
  1446. static PRBool
  1447. test_ucs2_chars
  1448. (
  1449.   void
  1450. )
  1451. {
  1452.   PRBool rv = PR_TRUE;
  1453.   int i;
  1454.   for( i = 0; i < sizeof(ucs2)/sizeof(ucs2[0]); i++ ) {
  1455.     struct ucs2 *e = &ucs2[i];
  1456.     PRBool result;
  1457.     unsigned char utf8[8];
  1458.     unsigned int len = 0;
  1459.     PRUint16 back = 0;
  1460.     (void)memset(utf8, 0, sizeof(utf8));
  1461.     
  1462.     result = sec_port_ucs2_utf8_conversion_function(PR_FALSE,
  1463.       (unsigned char *)&e->c, sizeof(e->c), utf8, sizeof(utf8), &len);
  1464.     if( !result ) {
  1465.       fprintf(stdout, "Failed to convert UCS-2 0x%04.4x to UTF-8n", e->c);
  1466.       rv = PR_FALSE;
  1467.       continue;
  1468.     }
  1469.     if( (len >= sizeof(utf8)) ||
  1470.         (strlen(e->utf8) != len) ||
  1471.         (utf8[len] = '', 0 != strcmp(e->utf8, utf8)) ) {
  1472.       fprintf(stdout, "Wrong conversion of UCS-2 0x%04.4x to UTF-8: ", e->c);
  1473.       dump_utf8("expected", e->utf8, ", ");
  1474.       dump_utf8("received", utf8, "n");
  1475.       rv = PR_FALSE;
  1476.       continue;
  1477.     }
  1478.     result = sec_port_ucs2_utf8_conversion_function(PR_TRUE,
  1479.       utf8, len, (unsigned char *)&back, sizeof(back), &len);
  1480.     if( !result ) {
  1481.       dump_utf8("Failed to convert UTF-8", utf8, "to UCS-2n");
  1482.       rv = PR_FALSE;
  1483.       continue;
  1484.     }
  1485.     if( (sizeof(back) != len) || (e->c != back) ) {
  1486.       dump_utf8("Wrong conversion of UTF-8", utf8, "to UCS-2:");
  1487.       fprintf(stdout, "expected 0x%08.8x, received 0x%08.8xn", e->c, back);
  1488.       rv = PR_FALSE;
  1489.       continue;
  1490.     }
  1491.   }
  1492.   return rv;
  1493. }
  1494. #ifdef UTF16
  1495. static PRBool
  1496. test_utf16_chars
  1497. (
  1498.   void
  1499. )
  1500. {
  1501.   PRBool rv = PR_TRUE;
  1502.   int i;
  1503.   for( i = 0; i < sizeof(utf16)/sizeof(utf16[0]); i++ ) {
  1504.     struct utf16 *e = &utf16[i];
  1505.     PRBool result;
  1506.     unsigned char utf8[8];
  1507.     unsigned int len = 0;
  1508.     PRUint32 back32 = 0;
  1509.     PRUint16 back[2];
  1510.     (void)memset(utf8, 0, sizeof(utf8));
  1511.     
  1512.     result = sec_port_ucs2_utf8_conversion_function(PR_FALSE, 
  1513.       (unsigned char *)&e->w[0], sizeof(e->w), utf8, sizeof(utf8), &len);
  1514.     if( !result ) {
  1515.       fprintf(stdout, "Failed to convert UTF-16 0x%04.4x 0x%04.4x to UTF-8n", 
  1516.               e->w[0], e->w[1]);
  1517.       rv = PR_FALSE;
  1518.       continue;
  1519.     }
  1520.     result = sec_port_ucs4_utf8_conversion_function(PR_TRUE,
  1521.       utf8, len, (unsigned char *)&back32, sizeof(back32), &len);
  1522.     if( 4 != len ) {
  1523.       fprintf(stdout, "Failed to convert UTF-16 0x%04.4x 0x%04.4x to UTF-8: "
  1524.               "unexpected len %dn", e->w[0], e->w[1], len);
  1525.       rv = PR_FALSE;
  1526.       continue;
  1527.     }
  1528.     utf8[len] = ''; /* null-terminate for printing */
  1529.     if( !result ) {
  1530.       dump_utf8("Failed to convert UTF-8", utf8, "to UCS-4 (utf-16 test)n");
  1531.       rv = PR_FALSE;
  1532.       continue;
  1533.     }
  1534.     if( (sizeof(back32) != len) || (e->c != back32) ) {
  1535.       fprintf(stdout, "Wrong conversion of UTF-16 0x%04.4x 0x%04.4x ", 
  1536.               e->w[0], e->w[1]);
  1537.       dump_utf8("to UTF-8", utf8, "and then to UCS-4: ");
  1538.       if( sizeof(back32) != len ) {
  1539.         fprintf(stdout, "len is %dn", len);
  1540.       } else {
  1541.         fprintf(stdout, "expected 0x%08.8x, received 0x%08.8xn", e->c, back32);
  1542.       }
  1543.       rv = PR_FALSE;
  1544.       continue;
  1545.     }
  1546.     (void)memset(utf8, 0, sizeof(utf8));
  1547.     back[0] = back[1] = 0;
  1548.     result = sec_port_ucs4_utf8_conversion_function(PR_FALSE,
  1549.       (unsigned char *)&e->c, sizeof(e->c), utf8, sizeof(utf8), &len);
  1550.     if( !result ) {
  1551.       fprintf(stdout, "Failed to convert UCS-4 0x%08.8x to UTF-8 (utf-16 test)n",
  1552.               e->c);
  1553.       rv = PR_FALSE;
  1554.       continue;
  1555.     }
  1556.     result = sec_port_ucs2_utf8_conversion_function(PR_TRUE,
  1557.       utf8, len, (unsigned char *)&back[0], sizeof(back), &len);
  1558.     if( 4 != len ) {
  1559.       fprintf(stdout, "Failed to convert UCS-4 0x%08.8x to UTF-8: "
  1560.               "unexpected len %dn", e->c, len);
  1561.       rv = PR_FALSE;
  1562.       continue;
  1563.     }
  1564.     utf8[len] = ''; /* null-terminate for printing */
  1565.     if( !result ) {
  1566.       dump_utf8("Failed to convert UTF-8", utf8, "to UTF-16n");
  1567.       rv = PR_FALSE;
  1568.       continue;
  1569.     }
  1570.     if( (sizeof(back) != len) || (e->w[0] != back[0]) || (e->w[1] != back[1]) ) {
  1571.       fprintf(stdout, "Wrong conversion of UCS-4 0x%08.8x to UTF-8", e->c);
  1572.       dump_utf8("", utf8, "and then to UTF-16:");
  1573.       if( sizeof(back) != len ) {
  1574.         fprintf(stdout, "len is %dn", len);
  1575.       } else {
  1576.         fprintf(stdout, "expected 0x%04.4x 0x%04.4x, received 0x%04.4x 0x%04.4xxn",
  1577.                 e->w[0], e->w[1], back[0], back[1]);
  1578.       }
  1579.       rv = PR_FALSE;
  1580.       continue;
  1581.     }
  1582.   }
  1583.   return rv;
  1584. }
  1585. #endif /* UTF16 */
  1586. static PRBool
  1587. test_zeroes
  1588. (
  1589.   void
  1590. )
  1591. {
  1592.   PRBool rv = PR_TRUE;
  1593.   PRBool result;
  1594.   PRUint32 lzero = 0;
  1595.   PRUint16 szero = 0;
  1596.   unsigned char utf8[8];
  1597.   unsigned int len = 0;
  1598.   PRUint32 lback = 1;
  1599.   PRUint16 sback = 1;
  1600.   (void)memset(utf8, 1, sizeof(utf8));
  1601.   result = sec_port_ucs4_utf8_conversion_function(PR_FALSE, 
  1602.     (unsigned char *)&lzero, sizeof(lzero), utf8, sizeof(utf8), &len);
  1603.   if( !result ) {
  1604.     fprintf(stdout, "Failed to convert UCS-4 0x00000000 to UTF-8n");
  1605.     rv = PR_FALSE;
  1606.   } else if( 1 != len ) {
  1607.     fprintf(stdout, "Wrong conversion of UCS-4 0x00000000: len = %dn", len);
  1608.     rv = PR_FALSE;
  1609.   } else if( '' != *utf8 ) {
  1610.     fprintf(stdout, "Wrong conversion of UCS-4 0x00000000: expected 00 ,"
  1611.             "received %02.2xn", (unsigned int)*utf8);
  1612.     rv = PR_FALSE;
  1613.   }
  1614.   result = sec_port_ucs4_utf8_conversion_function(PR_TRUE,
  1615.     "", 1, (unsigned char *)&lback, sizeof(lback), &len);
  1616.   if( !result ) {
  1617.     fprintf(stdout, "Failed to convert UTF-8 00 to UCS-4n");
  1618.     rv = PR_FALSE;
  1619.   } else if( 4 != len ) {
  1620.     fprintf(stdout, "Wrong conversion of UTF-8 00 to UCS-4: len = %dn", len);
  1621.     rv = PR_FALSE;
  1622.   } else if( 0 != lback ) {
  1623.     fprintf(stdout, "Wrong conversion of UTF-8 00 to UCS-4: "
  1624.             "expected 0x00000000, received 0x%08.8xn", lback);
  1625.     rv = PR_FALSE;
  1626.   }
  1627.   (void)memset(utf8, 1, sizeof(utf8));
  1628.   result = sec_port_ucs2_utf8_conversion_function(PR_FALSE, 
  1629.     (unsigned char *)&szero, sizeof(szero), utf8, sizeof(utf8), &len);
  1630.   if( !result ) {
  1631.     fprintf(stdout, "Failed to convert UCS-2 0x0000 to UTF-8n");
  1632.     rv = PR_FALSE;
  1633.   } else if( 1 != len ) {
  1634.     fprintf(stdout, "Wrong conversion of UCS-2 0x0000: len = %dn", len);
  1635.     rv = PR_FALSE;
  1636.   } else if( '' != *utf8 ) {
  1637.     fprintf(stdout, "Wrong conversion of UCS-2 0x0000: expected 00 ,"
  1638.             "received %02.2xn", (unsigned int)*utf8);
  1639.     rv = PR_FALSE;
  1640.   }
  1641.   result = sec_port_ucs2_utf8_conversion_function(PR_TRUE,
  1642.     "", 1, (unsigned char *)&sback, sizeof(sback), &len);
  1643.   if( !result ) {
  1644.     fprintf(stdout, "Failed to convert UTF-8 00 to UCS-2n");
  1645.     rv = PR_FALSE;
  1646.   } else if( 2 != len ) {
  1647.     fprintf(stdout, "Wrong conversion of UTF-8 00 to UCS-2: len = %dn", len);
  1648.     rv = PR_FALSE;
  1649.   } else if( 0 != sback ) {
  1650.     fprintf(stdout, "Wrong conversion of UTF-8 00 to UCS-2: "
  1651.             "expected 0x0000, received 0x%04.4xn", sback);
  1652.     rv = PR_FALSE;
  1653.   }
  1654.   return rv;
  1655. }
  1656. static PRBool
  1657. test_multichars
  1658. (
  1659.   void
  1660. )
  1661. {
  1662.   int i;
  1663.   unsigned int len, lenout;
  1664.   PRUint32 *ucs4s;
  1665.   char *ucs4_utf8;
  1666.   PRUint16 *ucs2s;
  1667.   char *ucs2_utf8;
  1668.   void *tmp;
  1669.   PRBool result;
  1670.   ucs4s = (PRUint32 *)calloc(sizeof(ucs4)/sizeof(ucs4[0]), sizeof(PRUint32));
  1671.   ucs2s = (PRUint16 *)calloc(sizeof(ucs2)/sizeof(ucs2[0]), sizeof(PRUint16));
  1672.   if( ((PRUint32 *)NULL == ucs4s) || ((PRUint16 *)NULL == ucs2s) ) {
  1673.     fprintf(stderr, "out of memoryn");
  1674.     exit(1);
  1675.   }
  1676.   len = 0;
  1677.   for( i = 0; i < sizeof(ucs4)/sizeof(ucs4[0]); i++ ) {
  1678.     ucs4s[i] = ucs4[i].c;
  1679.     len += strlen(ucs4[i].utf8);
  1680.   }
  1681.   ucs4_utf8 = (char *)malloc(len);
  1682.   len = 0;
  1683.   for( i = 0; i < sizeof(ucs2)/sizeof(ucs2[0]); i++ ) {
  1684.     ucs2s[i] = ucs2[i].c;
  1685.     len += strlen(ucs2[i].utf8);
  1686.   }
  1687.   ucs2_utf8 = (char *)malloc(len);
  1688.   if( ((char *)NULL == ucs4_utf8) || ((char *)NULL == ucs2_utf8) ) {
  1689.     fprintf(stderr, "out of memoryn");
  1690.     exit(1);
  1691.   }
  1692.   *ucs4_utf8 = '';
  1693.   for( i = 0; i < sizeof(ucs4)/sizeof(ucs4[0]); i++ ) {
  1694.     strcat(ucs4_utf8, ucs4[i].utf8);
  1695.   }
  1696.   *ucs2_utf8 = '';
  1697.   for( i = 0; i < sizeof(ucs2)/sizeof(ucs2[0]); i++ ) {
  1698.     strcat(ucs2_utf8, ucs2[i].utf8);
  1699.   }
  1700.   /* UTF-8 -> UCS-4 */
  1701.   len = sizeof(ucs4)/sizeof(ucs4[0]) * sizeof(PRUint32);
  1702.   tmp = calloc(len, 1);
  1703.   if( (void *)NULL == tmp ) {
  1704.     fprintf(stderr, "out of memoryn");
  1705.     exit(1);
  1706.   }
  1707.   result = sec_port_ucs4_utf8_conversion_function(PR_TRUE,
  1708.     ucs4_utf8, strlen(ucs4_utf8), tmp, len, &lenout);
  1709.   if( !result ) {
  1710.     fprintf(stdout, "Failed to convert much UTF-8 to UCS-4n");
  1711.     goto done;
  1712.   }
  1713.   if( lenout != len ) {
  1714.     fprintf(stdout, "Unexpected length converting much UTF-8 to UCS-4n");
  1715.     goto loser;
  1716.   }
  1717.   if( 0 != memcmp(ucs4s, tmp, len) ) {
  1718.     fprintf(stdout, "Wrong conversion of much UTF-8 to UCS-4n");
  1719.     goto loser;
  1720.   }
  1721.   free(tmp); tmp = (void *)NULL;
  1722.   /* UCS-4 -> UTF-8 */
  1723.   len = strlen(ucs4_utf8);
  1724.   tmp = calloc(len, 1);
  1725.   if( (void *)NULL == tmp ) {
  1726.     fprintf(stderr, "out of memoryn");
  1727.     exit(1);
  1728.   }
  1729.   result = sec_port_ucs4_utf8_conversion_function(PR_FALSE,
  1730.     (unsigned char *)ucs4s, sizeof(ucs4)/sizeof(ucs4[0]) * sizeof(PRUint32), 
  1731.     tmp, len, &lenout);
  1732.   if( !result ) {
  1733.     fprintf(stdout, "Failed to convert much UCS-4 to UTF-8n");
  1734.     goto done;
  1735.   }
  1736.   if( lenout != len ) {
  1737.     fprintf(stdout, "Unexpected length converting much UCS-4 to UTF-8n");
  1738.     goto loser;
  1739.   }
  1740.   if( 0 != strncmp(ucs4_utf8, tmp, len) ) {
  1741.     fprintf(stdout, "Wrong conversion of much UCS-4 to UTF-8n");
  1742.     goto loser;
  1743.   }
  1744.   free(tmp); tmp = (void *)NULL;
  1745.   /* UTF-8 -> UCS-2 */
  1746.   len = sizeof(ucs2)/sizeof(ucs2[0]) * sizeof(PRUint16);
  1747.   tmp = calloc(len, 1);
  1748.   if( (void *)NULL == tmp ) {
  1749.     fprintf(stderr, "out of memoryn");
  1750.     exit(1);
  1751.   }
  1752.   result = sec_port_ucs2_utf8_conversion_function(PR_TRUE,
  1753.     ucs2_utf8, strlen(ucs2_utf8), tmp, len, &lenout);
  1754.   if( !result ) {
  1755.     fprintf(stdout, "Failed to convert much UTF-8 to UCS-2n");
  1756.     goto done;
  1757.   }
  1758.   if( lenout != len ) {
  1759.     fprintf(stdout, "Unexpected length converting much UTF-8 to UCS-2n");
  1760.     goto loser;
  1761.   }
  1762.   if( 0 != memcmp(ucs2s, tmp, len) ) {
  1763.     fprintf(stdout, "Wrong conversion of much UTF-8 to UCS-2n");
  1764.     goto loser;
  1765.   }
  1766.   free(tmp); tmp = (void *)NULL;
  1767.   /* UCS-2 -> UTF-8 */
  1768.   len = strlen(ucs2_utf8);
  1769.   tmp = calloc(len, 1);
  1770.   if( (void *)NULL == tmp ) {
  1771.     fprintf(stderr, "out of memoryn");
  1772.     exit(1);
  1773.   }
  1774.   result = sec_port_ucs2_utf8_conversion_function(PR_FALSE,
  1775.     (unsigned char *)ucs2s, sizeof(ucs2)/sizeof(ucs2[0]) * sizeof(PRUint16), 
  1776.     tmp, len, &lenout);
  1777.   if( !result ) {
  1778.     fprintf(stdout, "Failed to convert much UCS-2 to UTF-8n");
  1779.     goto done;
  1780.   }
  1781.   if( lenout != len ) {
  1782.     fprintf(stdout, "Unexpected length converting much UCS-2 to UTF-8n");
  1783.     goto loser;
  1784.   }
  1785.   if( 0 != strncmp(ucs2_utf8, tmp, len) ) {
  1786.     fprintf(stdout, "Wrong conversion of much UCS-2 to UTF-8n");
  1787.     goto loser;
  1788.   }
  1789. #ifdef UTF16
  1790.   /* implement me */
  1791. #endif /* UTF16 */
  1792.   result = PR_TRUE;
  1793.   goto done;
  1794.  loser:
  1795.   result = PR_FALSE;
  1796.  done:
  1797.   free(ucs4s);
  1798.   free(ucs4_utf8);
  1799.   free(ucs2s);
  1800.   free(ucs2_utf8);
  1801.   if( (void *)NULL != tmp ) free(tmp);
  1802.   return result;
  1803. }
  1804. void
  1805. byte_order
  1806. (
  1807.   void
  1808. )
  1809. {
  1810.   /*
  1811.    * The implementation (now) expects the 16- and 32-bit characters
  1812.    * to be in network byte order, not host byte order.  Therefore I
  1813.    * have to byteswap all those test vectors above.  hton[ls] may be
  1814.    * functions, so I have to do this dynamically.  If you want to 
  1815.    * use this code to do host byte order conversions, just remove
  1816.    * the call in main() to this function.
  1817.    */
  1818.   int i;
  1819.   for( i = 0; i < sizeof(ucs4)/sizeof(ucs4[0]); i++ ) {
  1820.     struct ucs4 *e = &ucs4[i];
  1821.     e->c = htonl(e->c);
  1822.   }
  1823.   for( i = 0; i < sizeof(ucs2)/sizeof(ucs2[0]); i++ ) {
  1824.     struct ucs2 *e = &ucs2[i];
  1825.     e->c = htons(e->c);
  1826.   }
  1827. #ifdef UTF16
  1828.   for( i = 0; i < sizeof(utf16)/sizeof(utf16[0]); i++ ) {
  1829.     struct utf16 *e = &utf16[i];
  1830.     e->c = htonl(e->c);
  1831.     e->w[0] = htons(e->w[0]);
  1832.     e->w[1] = htons(e->w[1]);
  1833.   }
  1834. #endif /* UTF16 */
  1835.   return;
  1836. }
  1837. int
  1838. main
  1839. (
  1840.   int argc,
  1841.   char *argv[]
  1842. )
  1843. {
  1844.   byte_order();
  1845.   if( test_ucs4_chars() &&
  1846.       test_ucs2_chars() &&
  1847. #ifdef UTF16
  1848.       test_utf16_chars() &&
  1849. #endif /* UTF16 */
  1850.       test_zeroes() &&
  1851.       test_multichars() &&
  1852.       PR_TRUE ) {
  1853.     fprintf(stderr, "PASSn");
  1854.     return 1;
  1855.   } else {
  1856.     fprintf(stderr, "FAILn");
  1857.     return 0;
  1858.   }
  1859. }
  1860. #endif /* TEST_UTF8 */