encoding.c
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:26k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /*
  2.  * encoding.c : implements the encoding conversion functions needed for XML
  3.  *
  4.  * Related specs: 
  5.  * rfc2044        (UTF-8 and UTF-16) F. Yergeau Alis Technologies
  6.  * [ISO-10646]    UTF-8 and UTF-16 in Annexes
  7.  * [ISO-8859-1]   ISO Latin-1 characters codes.
  8.  * [UNICODE]      The Unicode Consortium, "The Unicode Standard --
  9.  *                Worldwide Character Encoding -- Version 1.0", Addison-
  10.  *                Wesley, Volume 1, 1991, Volume 2, 1992.  UTF-8 is
  11.  *                described in Unicode Technical Report #4.
  12.  * [US-ASCII]     Coded Character Set--7-bit American Standard Code for
  13.  *                Information Interchange, ANSI X3.4-1986.
  14.  *
  15.  * Original code for IsoLatin1 and UTF-16 by "Martin J. Duerst" <duerst@w3.org>
  16.  *
  17.  * See Copyright for the status of this software.
  18.  *
  19.  * Daniel.Veillard@w3.org
  20.  */
  21. #ifdef WIN32
  22. #include "win32config.h"
  23. #else
  24. #include "config.h"
  25. #endif
  26. #include <stdio.h>
  27. #include <string.h>
  28. #ifdef HAVE_CTYPE_H
  29. #include <ctype.h>
  30. #endif
  31. #ifdef HAVE_STDLIB_H
  32. #include <stdlib.h>
  33. #endif
  34. #include <libxml/encoding.h>
  35. #include <libxml/xmlmemory.h>
  36. xmlCharEncodingHandlerPtr xmlUTF16LEHandler = NULL;
  37. xmlCharEncodingHandlerPtr xmlUTF16BEHandler = NULL;
  38. /*
  39.  * From rfc2044: encoding of the Unicode values on UTF-8:
  40.  *
  41.  * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
  42.  * 0000 0000-0000 007F   0xxxxxxx
  43.  * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
  44.  * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx 
  45.  *
  46.  * I hope we won't use values > 0xFFFF anytime soon !
  47.  */
  48. /**
  49.  * xmlCheckUTF8: Check utf-8 string for legality.
  50.  * @utf: Pointer to putative utf-8 encoded string.
  51.  *
  52.  * Checks @utf for being valid utf-8. @utf is assumed to be
  53.  * null-terminated. This function is not super-strict, as it will
  54.  * allow longer utf-8 sequences than necessary. Note that Java is
  55.  * capable of producing these sequences if provoked. Also note, this
  56.  * routine checks for the 4-byte maxiumum size, but does not check for
  57.  * 0x10ffff maximum value.
  58.  *
  59.  * Return value: true if @utf is valid.
  60.  **/
  61. int
  62. xmlCheckUTF8(const unsigned char *utf)
  63. {
  64.     int ix;
  65.     unsigned char c;
  66.     for (ix = 0; (c = utf[ix]);) {
  67.         if (c & 0x80) {
  68.     if ((utf[ix + 1] & 0xc0) != 0x80)
  69.         return(0);
  70.     if ((c & 0xe0) == 0xe0) {
  71.         if ((utf[ix + 2] & 0xc0) != 0x80)
  72.     return(0);
  73.         if ((c & 0xf0) == 0xf0) {
  74.     if ((c & 0xf8) != 0xf0 || (utf[ix + 3] & 0xc0) != 0x80)
  75.         return(0);
  76.     ix += 4;
  77.     /* 4-byte code */
  78.         } else
  79.   /* 3-byte code */
  80.     ix += 3;
  81.     } else
  82.       /* 2-byte code */
  83.         ix += 2;
  84. } else
  85.     /* 1-byte code */
  86.     ix++;
  87.       }
  88.       return(1);
  89. }
  90. /**
  91.  * isolat1ToUTF8:
  92.  * @out:  a pointer to an array of bytes to store the result
  93.  * @outlen:  the length of @out
  94.  * @in:  a pointer to an array of ISO Latin 1 chars
  95.  * @inlen:  the length of @in
  96.  *
  97.  * Take a block of ISO Latin 1 chars in and try to convert it to an UTF-8
  98.  * block of chars out.
  99.  * Returns the number of byte written, or -1 by lack of space.
  100.  */
  101. int
  102. isolat1ToUTF8(unsigned char* out, int outlen,
  103.               const unsigned char* in, int *inlen) {
  104.     unsigned char* outstart= out;
  105.     unsigned char* outend= out+outlen;
  106.     const unsigned char* inend= in+*inlen;
  107.     unsigned char c;
  108.     while (in < inend) {
  109.         c= *in++;
  110.         if (c < 0x80) {
  111.             if (out >= outend)  return(-1);
  112.             *out++ = c;
  113.         }
  114.         else {
  115.             if (out >= outend)  return(-1);
  116.             *out++ = 0xC0 | (c >> 6);
  117.             if (out >= outend)  return(-1);
  118.             *out++ = 0x80 | (0x3F & c);
  119.         }
  120.     }
  121.     return(out-outstart);
  122. }
  123. /**
  124.  * UTF8Toisolat1:
  125.  * @out:  a pointer to an array of bytes to store the result
  126.  * @outlen:  the length of @out
  127.  * @in:  a pointer to an array of UTF-8 chars
  128.  * @inlen:  the length of @in
  129.  *
  130.  * Take a block of UTF-8 chars in and try to convert it to an ISO Latin 1
  131.  * block of chars out.
  132.  * TODO: UTF8Toisolat1 need a fallback mechanism ...
  133.  *
  134.  * Returns the number of byte written, or -1 by lack of space, or -2
  135.  *     if the transcoding fails (for *in is not valid utf8 string or
  136.  *     the result of transformation can't fit into the encoding we want)
  137.  * The value of @inlen after return is the number of octets consumed
  138.  *     as the return value is positive, else unpredictiable.
  139.  */
  140. int
  141. UTF8Toisolat1(unsigned char* out, int outlen,
  142.               const unsigned char* in, int *inlen) {
  143.     unsigned char* outstart= out;
  144.     unsigned char* outend= out+outlen;
  145.     const unsigned char* inend= in+*inlen;
  146.     unsigned char c;
  147.     while (in < inend) {
  148.         c= *in++;
  149.         if (c < 0x80) {
  150.             if (out >= outend)  return(-1);
  151.             *out++= c;
  152.         }
  153. else if (in == inend) {
  154.             *inlen -= 1;
  155.             break;
  156. }
  157. else if (((c & 0xFC) == 0xC0) && ((*in & 0xC0) == 0x80)) {
  158.     /* a two byte utf-8 and can be encoding as isolate1 */
  159.             *out++= ((c & 0x03) << 6) | (*in++ & 0x3F);
  160. }
  161. else
  162.     return(-2);
  163. /* TODO : some should be represent as "&#x____;" */
  164.     }
  165.     return(out-outstart);
  166. }
  167. /**
  168.  * UTF16LEToUTF8:
  169.  * @out:  a pointer to an array of bytes to store the result
  170.  * @outlen:  the length of @out
  171.  * @inb:  a pointer to an array of UTF-16LE passwd as a byte array
  172.  * @inlenb:  the length of @in in UTF-16LE chars
  173.  *
  174.  * Take a block of UTF-16LE ushorts in and try to convert it to an UTF-8
  175.  * block of chars out. This function assume the endian properity
  176.  * is the same between the native type of this machine and the
  177.  * inputed one.
  178.  *
  179.  * Returns the number of byte written, or -1 by lack of space, or -2
  180.  *     if the transcoding fails (for *in is not valid utf16 string)
  181.  *     The value of *inlen after return is the number of octets consumed
  182.  *     as the return value is positive, else unpredictiable.
  183.  */
  184. int
  185. UTF16LEToUTF8(unsigned char* out, int outlen,
  186.             const unsigned char* inb, int *inlenb)
  187. {
  188.     unsigned char* outstart= out;
  189.     unsigned char* outend= out+outlen;
  190.     unsigned short* in = (unsigned short*) inb;
  191.     unsigned short* inend;
  192.     unsigned int c, d, inlen;
  193.     unsigned char *tmp;
  194.     int bits;
  195.     if ((*inlenb % 2) == 1)
  196.         (*inlenb)--;
  197.     inlen = *inlenb / 2;
  198.     inend= in + inlen;
  199.     while (in < inend) {
  200. #ifdef BIG_ENDIAN
  201. tmp = (unsigned char *) in;
  202. c = *tmp++;
  203. c = c | (((unsigned int)*tmp) << 8);
  204. in++;
  205. #else /* BIG_ENDIAN */
  206.         c= *in++;
  207. #endif /* BIG_ENDIAN */
  208.         if ((c & 0xFC00) == 0xD800) {    /* surrogates */
  209.             if (in >= inend) {           /* (in > inend) shouldn't happens */
  210.                 (*inlenb) -= 2;
  211.                 break;
  212.             }
  213. #ifdef BIG_ENDIAN
  214.             tmp = (unsigned char *) in;
  215.             d = *tmp++;
  216.     d = d | (((unsigned int)*tmp) << 8);
  217.     in++;
  218. #else /* BIG_ENDIAN */
  219.             d = *in++;
  220. #endif /* BIG_ENDIAN */
  221.             if ((d & 0xFC00) == 0xDC00) {
  222.                 c &= 0x03FF;
  223.                 c <<= 10;
  224.                 c |= d & 0x03FF;
  225.                 c += 0x10000;
  226.             }
  227.             else
  228.         return(-2);
  229.         }
  230. /* assertion: c is a single UTF-4 value */
  231.         if (out >= outend)
  232.     return(-1);
  233.         if      (c <    0x80) {  *out++=  c;                bits= -6; }
  234.         else if (c <   0x800) {  *out++= ((c >>  6) & 0x1F) | 0xC0;  bits=  0; }
  235.         else if (c < 0x10000) {  *out++= ((c >> 12) & 0x0F) | 0xE0;  bits=  6; }
  236.         else                  {  *out++= ((c >> 18) & 0x07) | 0xF0;  bits= 12; }
  237.  
  238.         for ( ; bits >= 0; bits-= 6) {
  239.             if (out >= outend)
  240.         return(-1);
  241.             *out++= ((c >> bits) & 0x3F) | 0x80;
  242.         }
  243.     }
  244.     return(out-outstart);
  245. }
  246. /**
  247.  * UTF8ToUTF16LE:
  248.  * @outb:  a pointer to an array of bytes to store the result
  249.  * @outlen:  the length of @outb
  250.  * @in:  a pointer to an array of UTF-8 chars
  251.  * @inlen:  the length of @in
  252.  *
  253.  * Take a block of UTF-8 chars in and try to convert it to an UTF-16LE
  254.  * block of chars out.
  255.  * TODO: UTF8ToUTF16LE need a fallback mechanism ...
  256.  *
  257.  * Returns the number of byte written, or -1 by lack of space, or -2
  258.  *     if the transcoding failed. 
  259.  */
  260. int
  261. UTF8ToUTF16LE(unsigned char* outb, int outlen,
  262.             const unsigned char* in, int *inlen)
  263. {
  264.     unsigned short* out = (unsigned short*) outb;
  265.     unsigned short* outstart= out;
  266.     unsigned short* outend;
  267.     const unsigned char* inend= in+*inlen;
  268.     unsigned int c, d, trailing;
  269. #ifdef BIG_ENDIAN
  270.     unsigned char *tmp;
  271.     unsigned short tmp1, tmp2;
  272. #endif /* BIG_ENDIAN */
  273.     outlen /= 2; /* convert in short length */
  274.     outend = out + outlen;
  275.     while (in < inend) {
  276.       d= *in++;
  277.       if      (d < 0x80)  { c= d; trailing= 0; }
  278.       else if (d < 0xC0)
  279.           return(-2);    /* trailing byte in leading position */
  280.       else if (d < 0xE0)  { c= d & 0x1F; trailing= 1; }
  281.       else if (d < 0xF0)  { c= d & 0x0F; trailing= 2; }
  282.       else if (d < 0xF8)  { c= d & 0x07; trailing= 3; }
  283.       else
  284.           return(-2);    /* no chance for this in UTF-16 */
  285.       if (inend - in < trailing) {
  286.           *inlen -= (inend - in);
  287.           break;
  288.       } 
  289.       for ( ; trailing; trailing--) {
  290.           if ((in >= inend) || (((d= *in++) & 0xC0) != 0x80))
  291.       return(-1);
  292.           c <<= 6;
  293.           c |= d & 0x3F;
  294.       }
  295.       /* assertion: c is a single UTF-4 value */
  296.         if (c < 0x10000) {
  297.             if (out >= outend)
  298.         return(-1);
  299. #ifdef BIG_ENDIAN
  300.             tmp = (unsigned char *) out;
  301.             *tmp = c ;
  302.             *(tmp + 1) = c >> 8 ;
  303.             out++;
  304. #else /* BIG_ENDIAN */
  305.             *out++ = c;
  306. #endif /* BIG_ENDIAN */
  307.         }
  308.         else if (c < 0x110000) {
  309.             if (out+1 >= outend)
  310.         return(-1);
  311.             c -= 0x10000;
  312. #ifdef BIG_ENDIAN
  313.             tmp1 = 0xD800 | (c >> 10);
  314.             tmp = (unsigned char *) out;
  315.             *tmp = tmp1;
  316.             *(tmp + 1) = tmp1 >> 8;
  317.             out++;
  318.             tmp2 = 0xDC00 | (c & 0x03FF);
  319.             tmp = (unsigned char *) out;
  320.             *tmp  = tmp2;
  321.             *(tmp + 1) = tmp2 >> 8;
  322.             out++;
  323. #else /* BIG_ENDIAN */
  324.             *out++ = 0xD800 | (c >> 10);
  325.             *out++ = 0xDC00 | (c & 0x03FF);
  326. #endif /* BIG_ENDIAN */
  327.         }
  328.         else
  329.     return(-1);
  330.     }
  331.     return(out-outstart);
  332. }
  333. /**
  334.  * UTF16BEToUTF8:
  335.  * @out:  a pointer to an array of bytes to store the result
  336.  * @outlen:  the length of @out
  337.  * @inb:  a pointer to an array of UTF-16 passwd as a byte array
  338.  * @inlenb:  the length of @in in UTF-16 chars
  339.  *
  340.  * Take a block of UTF-16 ushorts in and try to convert it to an UTF-8
  341.  * block of chars out. This function assume the endian properity
  342.  * is the same between the native type of this machine and the
  343.  * inputed one.
  344.  *
  345.  * Returns the number of byte written, or -1 by lack of space, or -2
  346.  *     if the transcoding fails (for *in is not valid utf16 string)
  347.  * The value of *inlen after return is the number of octets consumed
  348.  *     as the return value is positive, else unpredictiable.
  349.  */
  350. int
  351. UTF16BEToUTF8(unsigned char* out, int outlen,
  352.             const unsigned char* inb, int *inlenb)
  353. {
  354.     unsigned char* outstart= out;
  355.     unsigned char* outend= out+outlen;
  356.     unsigned short* in = (unsigned short*) inb;
  357.     unsigned short* inend;
  358.     unsigned int c, d, inlen;
  359. #ifdef BIG_ENDIAN
  360. #else /* BIG_ENDIAN */
  361.     unsigned char *tmp;
  362. #endif /* BIG_ENDIAN */    
  363.     int bits;
  364.     if ((*inlenb % 2) == 1)
  365.         (*inlenb)--;
  366.     inlen = *inlenb / 2;
  367.     inend= in + inlen;
  368.     while (in < inend) {
  369. #ifdef BIG_ENDIAN    
  370.         c= *in++;
  371. #else
  372.         tmp = (unsigned char *) in;
  373. c = *tmp++;
  374. c = c << 8;
  375. c = c | (unsigned int) *tmp;
  376. in++;
  377. #endif
  378.         if ((c & 0xFC00) == 0xD800) {    /* surrogates */
  379.     if (in >= inend) {           /* (in > inend) shouldn't happens */
  380.         (*inlenb) -= 2;
  381. break;
  382.     }
  383. #ifdef BIG_ENDIAN
  384.             d= *in++;
  385. #else
  386.             tmp = (unsigned char *) in;
  387.     d = *tmp++;
  388.     d = d << 8;
  389.     d = d | (unsigned int) *tmp;
  390.     in++;
  391. #endif     
  392.             if ((d & 0xFC00) == 0xDC00) {
  393.                 c &= 0x03FF;
  394.                 c <<= 10;
  395.                 c |= d & 0x03FF;
  396.                 c += 0x10000;
  397.             }
  398.             else 
  399.         return(-2);
  400.         }
  401. /* assertion: c is a single UTF-4 value */
  402.         if (out >= outend) 
  403.     return(-1);
  404.         if      (c <    0x80) {  *out++=  c;                bits= -6; }
  405.         else if (c <   0x800) {  *out++= ((c >>  6) & 0x1F) | 0xC0;  bits=  0; }
  406.         else if (c < 0x10000) {  *out++= ((c >> 12) & 0x0F) | 0xE0;  bits=  6; }
  407.         else                  {  *out++= ((c >> 18) & 0x07) | 0xF0;  bits= 12; }
  408.  
  409.         for ( ; bits >= 0; bits-= 6) {
  410.             if (out >= outend) 
  411.         return(-1);
  412.             *out++= ((c >> bits) & 0x3F) | 0x80;
  413.         }
  414.     }
  415.     return(out-outstart);
  416. }
  417. /**
  418.  * UTF8ToUTF16BE:
  419.  * @outb:  a pointer to an array of bytes to store the result
  420.  * @outlen:  the length of @outb
  421.  * @in:  a pointer to an array of UTF-8 chars
  422.  * @inlen:  the length of @in
  423.  *
  424.  * Take a block of UTF-8 chars in and try to convert it to an UTF-16BE
  425.  * block of chars out.
  426.  * TODO: UTF8ToUTF16BE need a fallback mechanism ...
  427.  *
  428.  * Returns the number of byte written, or -1 by lack of space, or -2
  429.  *     if the transcoding failed. 
  430.  */
  431. int
  432. UTF8ToUTF16BE(unsigned char* outb, int outlen,
  433.             const unsigned char* in, int *inlen)
  434. {
  435.     unsigned short* out = (unsigned short*) outb;
  436.     unsigned short* outstart= out;
  437.     unsigned short* outend;
  438.     const unsigned char* inend= in+*inlen;
  439.     unsigned int c, d, trailing;
  440. #ifdef BIG_ENDIAN
  441. #else
  442.     unsigned char *tmp;
  443.     unsigned short tmp1, tmp2;
  444. #endif /* BIG_ENDIAN */    
  445.     outlen /= 2; /* convert in short length */
  446.     outend = out + outlen;
  447.     while (in < inend) {
  448.       d= *in++;
  449.       if      (d < 0x80)  { c= d; trailing= 0; }
  450.       else if (d < 0xC0)
  451.           return(-2);    /* trailing byte in leading position */
  452.       else if (d < 0xE0)  { c= d & 0x1F; trailing= 1; }
  453.       else if (d < 0xF0)  { c= d & 0x0F; trailing= 2; }
  454.       else if (d < 0xF8)  { c= d & 0x07; trailing= 3; }
  455.       else
  456.           return(-2);    /* no chance for this in UTF-16 */
  457.       if (inend - in < trailing) {
  458.           *inlen -= (inend - in);
  459.           break;
  460.       } 
  461.       for ( ; trailing; trailing--) {
  462.           if ((in >= inend) || (((d= *in++) & 0xC0) != 0x80))  return(-1);
  463.           c <<= 6;
  464.           c |= d & 0x3F;
  465.       }
  466.       /* assertion: c is a single UTF-4 value */
  467.         if (c < 0x10000) {
  468.             if (out >= outend)  return(-1);
  469. #ifdef BIG_ENDIAN
  470.             *out++ = c;
  471. #else
  472.             tmp = (unsigned char *) out;
  473.             *tmp = c >> 8;
  474.             *(tmp + 1) = c;
  475.             out++;
  476. #endif /* BIG_ENDIAN */
  477.         }
  478.         else if (c < 0x110000) {
  479.             if (out+1 >= outend)  return(-1);
  480.             c -= 0x10000;
  481. #ifdef BIG_ENDIAN
  482.             *out++ = 0xD800 | (c >> 10);
  483.             *out++ = 0xDC00 | (c & 0x03FF);
  484. #else
  485.             tmp1 = 0xD800 | (c >> 10);
  486.             tmp = (unsigned char *) out;
  487.             *tmp = tmp1 >> 8;
  488.             *(tmp + 1) = tmp1;
  489.             out++;
  490.             tmp2 = 0xDC00 | (c & 0x03FF);
  491.             tmp = (unsigned char *) out;
  492.             *tmp = tmp2 >> 8;
  493.             *(tmp + 1) = tmp2;
  494.             out++;
  495. #endif
  496.         }
  497.         else  return(-1);
  498.     }
  499.     return(out-outstart);
  500. }
  501. /**
  502.  * xmlDetectCharEncoding:
  503.  * @in:  a pointer to the first bytes of the XML entity, must be at least
  504.  *       4 bytes long.
  505.  * @len:  pointer to the length of the buffer
  506.  *
  507.  * Guess the encoding of the entity using the first bytes of the entity content
  508.  * accordingly of the non-normative appendix F of the XML-1.0 recommendation.
  509.  * 
  510.  * Returns one of the XML_CHAR_ENCODING_... values.
  511.  */
  512. xmlCharEncoding
  513. xmlDetectCharEncoding(const unsigned char* in, int len)
  514. {
  515.     if (len >= 4) {
  516. if ((in[0] == 0x00) && (in[1] == 0x00) &&
  517.     (in[2] == 0x00) && (in[3] == 0x3C))
  518.     return(XML_CHAR_ENCODING_UCS4BE);
  519. if ((in[0] == 0x3C) && (in[1] == 0x00) &&
  520.     (in[2] == 0x00) && (in[3] == 0x00))
  521.     return(XML_CHAR_ENCODING_UCS4LE);
  522. if ((in[0] == 0x00) && (in[1] == 0x00) &&
  523.     (in[2] == 0x3C) && (in[3] == 0x00))
  524.     return(XML_CHAR_ENCODING_UCS4_2143);
  525. if ((in[0] == 0x00) && (in[1] == 0x3C) &&
  526.     (in[2] == 0x00) && (in[3] == 0x00))
  527.     return(XML_CHAR_ENCODING_UCS4_3412);
  528. if ((in[0] == 0x4C) && (in[1] == 0x6F) &&
  529.     (in[2] == 0xA7) && (in[3] == 0x94))
  530.     return(XML_CHAR_ENCODING_EBCDIC);
  531. if ((in[0] == 0x3C) && (in[1] == 0x3F) &&
  532.     (in[2] == 0x78) && (in[3] == 0x6D))
  533.     return(XML_CHAR_ENCODING_UTF8);
  534.     }
  535.     if (len >= 2) {
  536. if ((in[0] == 0xFE) && (in[1] == 0xFF))
  537.     return(XML_CHAR_ENCODING_UTF16BE);
  538. if ((in[0] == 0xFF) && (in[1] == 0xFE))
  539.     return(XML_CHAR_ENCODING_UTF16LE);
  540.     }
  541.     return(XML_CHAR_ENCODING_NONE);
  542. }
  543. /**
  544.  * xmlParseCharEncoding:
  545.  * @name:  the encoding name as parsed, in UTF-8 format (ASCII actually)
  546.  *
  547.  * Conpare the string to the known encoding schemes already known. Note
  548.  * that the comparison is case insensitive accordingly to the section
  549.  * [XML] 4.3.3 Character Encoding in Entities.
  550.  * 
  551.  * Returns one of the XML_CHAR_ENCODING_... values or XML_CHAR_ENCODING_NONE
  552.  * if not recognized.
  553.  */
  554. xmlCharEncoding
  555. xmlParseCharEncoding(const char* name)
  556. {
  557.     char upper[500];
  558.     int i;
  559.     for (i = 0;i < 499;i++) {
  560.         upper[i] = toupper(name[i]);
  561. if (upper[i] == 0) break;
  562.     }
  563.     upper[i] = 0;
  564.     if (!strcmp(upper, "")) return(XML_CHAR_ENCODING_NONE);
  565.     if (!strcmp(upper, "UTF-8")) return(XML_CHAR_ENCODING_UTF8);
  566.     if (!strcmp(upper, "UTF8")) return(XML_CHAR_ENCODING_UTF8);
  567.     /*
  568.      * NOTE: if we were able to parse this, the endianness of UTF16 is
  569.      *       already found and in use
  570.      */
  571.     if (!strcmp(upper, "UTF-16")) return(XML_CHAR_ENCODING_UTF16LE);
  572.     if (!strcmp(upper, "UTF16")) return(XML_CHAR_ENCODING_UTF16LE);
  573.     
  574.     if (!strcmp(upper, "ISO-10646-UCS-2")) return(XML_CHAR_ENCODING_UCS2);
  575.     if (!strcmp(upper, "UCS-2")) return(XML_CHAR_ENCODING_UCS2);
  576.     if (!strcmp(upper, "UCS2")) return(XML_CHAR_ENCODING_UCS2);
  577.     /*
  578.      * NOTE: if we were able to parse this, the endianness of UCS4 is
  579.      *       already found and in use
  580.      */
  581.     if (!strcmp(upper, "ISO-10646-UCS-4")) return(XML_CHAR_ENCODING_UCS4LE);
  582.     if (!strcmp(upper, "UCS-4")) return(XML_CHAR_ENCODING_UCS4LE);
  583.     if (!strcmp(upper, "UCS4")) return(XML_CHAR_ENCODING_UCS4LE);
  584.     
  585.     if (!strcmp(upper,  "ISO-8859-1")) return(XML_CHAR_ENCODING_8859_1);
  586.     if (!strcmp(upper,  "ISO-LATIN-1")) return(XML_CHAR_ENCODING_8859_1);
  587.     if (!strcmp(upper,  "ISO LATIN 1")) return(XML_CHAR_ENCODING_8859_1);
  588.     if (!strcmp(upper,  "ISO-8859-2")) return(XML_CHAR_ENCODING_8859_2);
  589.     if (!strcmp(upper,  "ISO-LATIN-2")) return(XML_CHAR_ENCODING_8859_2);
  590.     if (!strcmp(upper,  "ISO LATIN 2")) return(XML_CHAR_ENCODING_8859_2);
  591.     if (!strcmp(upper,  "ISO-8859-3")) return(XML_CHAR_ENCODING_8859_3);
  592.     if (!strcmp(upper,  "ISO-8859-4")) return(XML_CHAR_ENCODING_8859_4);
  593.     if (!strcmp(upper,  "ISO-8859-5")) return(XML_CHAR_ENCODING_8859_5);
  594.     if (!strcmp(upper,  "ISO-8859-6")) return(XML_CHAR_ENCODING_8859_6);
  595.     if (!strcmp(upper,  "ISO-8859-7")) return(XML_CHAR_ENCODING_8859_7);
  596.     if (!strcmp(upper,  "ISO-8859-8")) return(XML_CHAR_ENCODING_8859_8);
  597.     if (!strcmp(upper,  "ISO-8859-9")) return(XML_CHAR_ENCODING_8859_9);
  598.     if (!strcmp(upper, "ISO-2022-JP")) return(XML_CHAR_ENCODING_2022_JP);
  599.     if (!strcmp(upper, "Shift_JIS")) return(XML_CHAR_ENCODING_SHIFT_JIS);
  600.     if (!strcmp(upper, "EUC-JP")) return(XML_CHAR_ENCODING_EUC_JP);
  601.     return(XML_CHAR_ENCODING_ERROR);
  602. }
  603. /****************************************************************
  604.  * *
  605.  * Char encoding handlers *
  606.  * *
  607.  ****************************************************************/
  608. /* the size should be growable, but it's not a big deal ... */
  609. #define MAX_ENCODING_HANDLERS 50
  610. static xmlCharEncodingHandlerPtr *handlers = NULL;
  611. static int nbCharEncodingHandler = 0;
  612. /*
  613.  * The default is UTF-8 for XML, that's also the default used for the
  614.  * parser internals, so the default encoding handler is NULL
  615.  */
  616. static xmlCharEncodingHandlerPtr xmlDefaultCharEncodingHandler = NULL;
  617. /**
  618.  * xmlNewCharEncodingHandler:
  619.  * @name:  the encoding name, in UTF-8 format (ASCII actually)
  620.  * @input:  the xmlCharEncodingInputFunc to read that encoding
  621.  * @output:  the xmlCharEncodingOutputFunc to write that encoding
  622.  *
  623.  * Create and registers an xmlCharEncodingHandler.
  624.  * Returns the xmlCharEncodingHandlerPtr created (or NULL in case of error).
  625.  */
  626. xmlCharEncodingHandlerPtr
  627. xmlNewCharEncodingHandler(const char *name, 
  628.                           xmlCharEncodingInputFunc input,
  629.                           xmlCharEncodingOutputFunc output) {
  630.     xmlCharEncodingHandlerPtr handler;
  631.     char upper[500];
  632.     int i;
  633.     char *up = 0;
  634.     /*
  635.      * Keep only the uppercase version of the encoding.
  636.      */
  637.     if (name == NULL) {
  638.         fprintf(stderr, "xmlNewCharEncodingHandler : no name !n");
  639. return(NULL);
  640.     }
  641.     for (i = 0;i < 499;i++) {
  642.         upper[i] = toupper(name[i]);
  643. if (upper[i] == 0) break;
  644.     }
  645.     upper[i] = 0;
  646.     up = xmlMemStrdup(upper);
  647.     if (up == NULL) {
  648.         fprintf(stderr, "xmlNewCharEncodingHandler : out of memory !n");
  649. return(NULL);
  650.     }
  651.     /*
  652.      * allocate and fill-up an handler block.
  653.      */
  654.     handler = (xmlCharEncodingHandlerPtr)
  655.               xmlMalloc(sizeof(xmlCharEncodingHandler));
  656.     if (handler == NULL) {
  657.         fprintf(stderr, "xmlNewCharEncodingHandler : out of memory !n");
  658. return(NULL);
  659.     }
  660.     handler->input = input;
  661.     handler->output = output;
  662.     handler->name = up;
  663.     /*
  664.      * registers and returns the handler.
  665.      */
  666.     xmlRegisterCharEncodingHandler(handler);
  667.     return(handler);
  668. }
  669. /**
  670.  * xmlInitCharEncodingHandlers:
  671.  *
  672.  * Initialize the char encoding support, it registers the default
  673.  * encoding supported.
  674.  * NOTE: while public, this function usually doesn't need to be called
  675.  *       in normal processing.
  676.  */
  677. void
  678. xmlInitCharEncodingHandlers(void) {
  679.     if (handlers != NULL) return;
  680.     handlers = (xmlCharEncodingHandlerPtr *)
  681.         xmlMalloc(MAX_ENCODING_HANDLERS * sizeof(xmlCharEncodingHandlerPtr));
  682.     if (handlers == NULL) {
  683.         fprintf(stderr, "xmlInitCharEncodingHandlers : out of memory !n");
  684. return;
  685.     }
  686.     xmlNewCharEncodingHandler("UTF-8", NULL, NULL);
  687.     xmlUTF16LEHandler = 
  688.           xmlNewCharEncodingHandler("UTF-16LE", UTF16LEToUTF8, UTF8ToUTF16LE);
  689.     xmlUTF16BEHandler = 
  690.           xmlNewCharEncodingHandler("UTF-16BE", UTF16BEToUTF8, UTF8ToUTF16BE);
  691.     xmlNewCharEncodingHandler("ISO-8859-1", isolat1ToUTF8, UTF8Toisolat1);
  692. }
  693. /**
  694.  * xmlCleanupCharEncodingHandlers:
  695.  *
  696.  * Cleanup the memory allocated for the char encoding support, it
  697.  * unregisters all the encoding handlers.
  698.  */
  699. void
  700. xmlCleanupCharEncodingHandlers(void) {
  701.     if (handlers == NULL) return;
  702.     for (;nbCharEncodingHandler > 0;) {
  703.         nbCharEncodingHandler--;
  704. if (handlers[nbCharEncodingHandler] != NULL) {
  705.     xmlFree(handlers[nbCharEncodingHandler]->name);
  706.     xmlFree(handlers[nbCharEncodingHandler]);
  707. }
  708.     }
  709.     xmlFree(handlers);
  710.     handlers = NULL;
  711.     nbCharEncodingHandler = 0;
  712.     xmlDefaultCharEncodingHandler = NULL;
  713. }
  714. /**
  715.  * xmlRegisterCharEncodingHandler:
  716.  * @handler:  the xmlCharEncodingHandlerPtr handler block
  717.  *
  718.  * Register the char encoding handler, surprizing, isn't it ?
  719.  */
  720. void
  721. xmlRegisterCharEncodingHandler(xmlCharEncodingHandlerPtr handler) {
  722.     if (handlers == NULL) xmlInitCharEncodingHandlers();
  723.     if (handler == NULL) {
  724.         fprintf(stderr, "xmlRegisterCharEncodingHandler: NULL handler !n");
  725. return;
  726.     }
  727.     if (nbCharEncodingHandler >= MAX_ENCODING_HANDLERS) {
  728.         fprintf(stderr, 
  729. "xmlRegisterCharEncodingHandler: Too many handler registeredn");
  730.         fprintf(stderr, "tincrease MAX_ENCODING_HANDLERS : %sn", __FILE__);
  731. return;
  732.     }
  733.     handlers[nbCharEncodingHandler++] = handler;
  734. }
  735. /**
  736.  * xmlGetCharEncodingHandler:
  737.  * @enc:  an xmlCharEncoding value.
  738.  *
  739.  * Search in the registrered set the handler able to read/write that encoding.
  740.  *
  741.  * Returns the handler or NULL if not found
  742.  */
  743. xmlCharEncodingHandlerPtr
  744. xmlGetCharEncodingHandler(xmlCharEncoding enc) {
  745.     if (handlers == NULL) xmlInitCharEncodingHandlers();
  746.     switch (enc) {
  747.         case XML_CHAR_ENCODING_ERROR:
  748.     return(NULL);
  749.         case XML_CHAR_ENCODING_NONE:
  750.     return(NULL);
  751.         case XML_CHAR_ENCODING_UTF8:
  752.     return(NULL);
  753.         case XML_CHAR_ENCODING_UTF16LE:
  754.     return(xmlUTF16LEHandler);
  755.         case XML_CHAR_ENCODING_UTF16BE:
  756.     return(xmlUTF16BEHandler);
  757.         case XML_CHAR_ENCODING_EBCDIC:
  758.     return(NULL);
  759.         case XML_CHAR_ENCODING_UCS4LE:
  760.     return(NULL);
  761.         case XML_CHAR_ENCODING_UCS4BE:
  762.     return(NULL);
  763.         case XML_CHAR_ENCODING_UCS4_2143:
  764.     return(NULL);
  765.         case XML_CHAR_ENCODING_UCS4_3412:
  766.     return(NULL);
  767.         case XML_CHAR_ENCODING_UCS2:
  768.     return(NULL);
  769.         case XML_CHAR_ENCODING_8859_1:
  770.     return(NULL);
  771.         case XML_CHAR_ENCODING_8859_2:
  772.     return(NULL);
  773.         case XML_CHAR_ENCODING_8859_3:
  774.     return(NULL);
  775.         case XML_CHAR_ENCODING_8859_4:
  776.     return(NULL);
  777.         case XML_CHAR_ENCODING_8859_5:
  778.     return(NULL);
  779.         case XML_CHAR_ENCODING_8859_6:
  780.     return(NULL);
  781.         case XML_CHAR_ENCODING_8859_7:
  782.     return(NULL);
  783.         case XML_CHAR_ENCODING_8859_8:
  784.     return(NULL);
  785.         case XML_CHAR_ENCODING_8859_9:
  786.     return(NULL);
  787.         case XML_CHAR_ENCODING_2022_JP:
  788.         case XML_CHAR_ENCODING_SHIFT_JIS:
  789.         case XML_CHAR_ENCODING_EUC_JP:
  790.     return(NULL);
  791.     }
  792.     return(NULL);
  793. }
  794. /**
  795.  * xmlGetCharEncodingHandler:
  796.  * @enc:  a string describing the char encoding.
  797.  *
  798.  * Search in the registrered set the handler able to read/write that encoding.
  799.  *
  800.  * Returns the handler or NULL if not found
  801.  */
  802. xmlCharEncodingHandlerPtr
  803. xmlFindCharEncodingHandler(const char *name) {
  804.     char upper[500];
  805.     int i;
  806.     if (handlers == NULL) xmlInitCharEncodingHandlers();
  807.     if (name == NULL) return(xmlDefaultCharEncodingHandler);
  808.     if (name[0] == 0) return(xmlDefaultCharEncodingHandler);
  809.     for (i = 0;i < 499;i++) {
  810.         upper[i] = toupper(name[i]);
  811. if (upper[i] == 0) break;
  812.     }
  813.     upper[i] = 0;
  814.     for (i = 0;i < nbCharEncodingHandler; i++)
  815.         if (!strcmp(name, handlers[i]->name))
  816.     return(handlers[i]);
  817.     return(NULL);
  818. }