iconv.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:5k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: iconv.c,v $
  4.  * PRODUCTION Revision 1000.0  2003/10/29 20:34:45  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R1.2
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
  10.  * Copyright (C) 1998-1999  Brian Bruns
  11.  *
  12.  * This library is free software; you can redistribute it and/or
  13.  * modify it under the terms of the GNU Library General Public
  14.  * License as published by the Free Software Foundation; either
  15.  * version 2 of the License, or (at your option) any later version.
  16.  *
  17.  * This library is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  20.  * Library General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU Library General Public
  23.  * License along with this library; if not, write to the
  24.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  25.  * Boston, MA 02111-1307, USA.
  26.  */
  27. /*
  28. ** iconv.c, handle all the conversion stuff without spreading #if HAVE_ICONV 
  29. ** all over the other code
  30. */
  31. #include <tds_config.h>
  32. #include "tds.h"
  33. #include "tdsutil.h"
  34. #include "tdsiconv.h"
  35. #if HAVE_ICONV
  36. #include <iconv.h>
  37. #endif
  38. #ifdef DMALLOC
  39. #include <dmalloc.h>
  40. #endif
  41. void tds_iconv_open(TDSSOCKET *tds, char *charset)
  42. {
  43. TDSICONVINFO *iconv_info;
  44. iconv_info = (TDSICONVINFO *) tds->iconv_info;
  45. #if HAVE_ICONV
  46. iconv_info->cdto = iconv_open("UCS-2LE",charset);
  47. if (iconv_info->cdto == (iconv_t)-1) {
  48. iconv_info->use_iconv = 0;
  49. return;
  50. }
  51. iconv_info->cdfrom = iconv_open(charset, "UCS-2LE");
  52. if (iconv_info->cdfrom == (iconv_t)-1) {
  53. iconv_info->use_iconv = 0;
  54. return;
  55. }
  56. iconv_info->use_iconv = 1; 
  57. /* temporarily disable */
  58. /* iconv_info->use_iconv = 0; */
  59. #else 
  60. iconv_info->use_iconv = 0;
  61. #endif
  62. }
  63. void tds_iconv_close(TDSSOCKET *tds)
  64. {
  65. TDSICONVINFO *iconv_info;
  66. iconv_info = (TDSICONVINFO *) tds->iconv_info;
  67. #if HAVE_ICONV
  68. if (iconv_info->cdto != (iconv_t)-1) {
  69. iconv_close(iconv_info->cdto);
  70. }
  71. if (iconv_info->cdfrom != (iconv_t)-1) {
  72. iconv_close(iconv_info->cdfrom);
  73. }
  74. #endif 
  75. }
  76. /**
  77.  * tds7_unicode2ascii()
  78.  * Note: The dest buf must be large enough to handle 'len' + 1 bytes.
  79.  * in_string have not to be terminated and len characters (2 byte) long
  80.  */
  81. char *tds7_unicode2ascii(TDSSOCKET *tds, const char *in_string, char *out_string, int len)
  82. {
  83. TDSICONVINFO *iconv_info;
  84. int i, j;
  85. if (!in_string || (len < 0)) return NULL;
  86. #if HAVE_ICONV
  87. iconv_info = tds->iconv_info;
  88. if (iconv_info->use_iconv) {
  89.   const char *in_ptr;
  90.   char *out_ptr;
  91.   size_t out_bytes, in_bytes;
  92.   char quest_mark[] = "?"; /* best to live no-const */
  93.   const char *pquest_mark; 
  94.   size_t lquest_mark;
  95.       out_bytes = len;
  96.       in_bytes = len * 2;
  97.       in_ptr = (char *)in_string;
  98.       out_ptr = out_string;
  99.       while (iconv(iconv_info->cdfrom, &in_ptr, &in_bytes, &out_ptr, &out_bytes) == (size_t)-1) {
  100. /* iconv call can reset errno */
  101. i = errno;
  102. /* reset iconv state */
  103. iconv(iconv_info->cdfrom, NULL, NULL, NULL, NULL);
  104. if (i != EILSEQ) break;
  105. /* skip one UCS-2 sequnce */
  106. in_ptr += 2;
  107. in_bytes -= 2;
  108. /* replace invalid with '?' */
  109. pquest_mark = quest_mark;
  110. lquest_mark = 2;
  111. iconv(iconv_info->cdfrom, &pquest_mark, &lquest_mark, &out_ptr, &out_bytes);
  112. if (out_bytes == 0) break;
  113. }
  114. /* FIXME best method ?? there is no way to return 
  115.  * less or more than len characters */
  116. /* something went wrong fill remaining with zeroes 
  117.  * avoiding returning garbage data */
  118. if (out_bytes) memset(out_ptr,0,out_bytes);
  119. out_string[len] = '';
  120.       return out_string;
  121. }
  122. #endif
  123. /* no iconv, strip high order byte if zero or replace with '?' 
  124.  * this is the same of converting to ISO8859-1 charset using iconv */
  125. /* FIXME update docs */
  126. #ifdef NCBI_FTDS
  127. for (i= j= 0; i != len; j+= 2) {
  128. out_string[i++]= in_string[j];
  129. }
  130. #else
  131. for (i=j=0;i<len;j+= 2) {
  132. out_string[i++] = 
  133. in_string[j+1] ? '?' : in_string[j];
  134. }
  135. #endif
  136. out_string[i]='';
  137. return out_string;
  138. }
  139. /**
  140.  * tds7_ascii2unicode()
  141.  * Convert a string to Unicode
  142.  * Note: output string is not terminated
  143.  */
  144. unsigned char *
  145. tds7_ascii2unicode(TDSSOCKET *tds, const char *in_string, char *out_string, int maxlen)
  146. {
  147. register int out_pos = 0;
  148. register int i; 
  149. size_t string_length;
  150. TDSICONVINFO *iconv_info;
  151. #if HAVE_ICONV
  152. const char *in_ptr;
  153. char *out_ptr;
  154. size_t out_bytes, in_bytes;
  155. #endif
  156. if (!in_string) return NULL;
  157. string_length = strlen(in_string);
  158. #if HAVE_ICONV
  159. iconv_info = tds->iconv_info;
  160. if (iconv_info->use_iconv) {
  161.       out_bytes = maxlen;
  162.       in_bytes = string_length;
  163.       in_ptr = (char *)in_string;
  164.       out_ptr = out_string;
  165.       iconv(iconv_info->cdto, &in_ptr, &in_bytes, &out_ptr, &out_bytes);
  166.       return out_string;
  167. }
  168. #endif
  169. /* no iconv, add null high order byte to convert 7bit ascii to unicode */
  170. if (string_length*2 > maxlen)
  171. string_length = maxlen >> 1;
  172. for (i=0;i<string_length;i++) {
  173. out_string[out_pos++]=in_string[i];
  174. out_string[out_pos++]='';
  175. }
  176. return out_string;
  177. }