iconv_cnv.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:21k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /**
  57.  * $Log: iconv_cnv.cpp,v $
  58.  * Revision 1.1  2001/06/25 16:19:14  tng
  59.  * Rename iconv_cnv.c to iconv_cnv.cpp.  AS400 changes by Linda Swan.
  60.  *
  61.  * Revision 1.3  2001/06/19 19:31:04  tng
  62.  * Latest AS/400 update.
  63.  *
  64.  * Revision 1.2  2000/09/12 17:06:49  aruna1
  65.  * Replaced INDEX_OUTOFBOUNDS error to BUFFER_OVERFLOW error for toUnicode and from_Unicode functions for compatibility with icu 1.6
  66.  *
  67.  * Revision 1.1  2000/02/10 18:08:28  abagchi
  68.  * Initial checkin
  69.  *
  70.  */
  71. #include <stdio.h>
  72. #include <stdlib.h>
  73. #include <unistd.h>
  74. #include <errno.h>
  75. #include <iconv_util.hpp>
  76. #include <iconv_cnv.hpp>
  77. #include <qmhrtvm.h>
  78. #include <qusec.h>
  79. #include <util/Platforms/OS400/OS400PlatformUtils.hpp>
  80. #include <iconv.h>
  81. #include <errno.h>
  82. #define CHUNK_SIZE 5*1024
  83. void Convert_toUnicode(UConverter *,
  84.      UChar **,
  85.      const UChar *,
  86.      const char **,
  87.      const char *,
  88.      int32_t* offsets,
  89.      int,
  90.      UErrorCode *);
  91. void Convert_fromUnicode(UConverter *,
  92.        char **,
  93.        const char *,
  94.        const UChar **,
  95.        const UChar *,
  96.        int32_t* offsets,
  97.        int,
  98.        UErrorCode *);
  99. UChar getNextUChar(UConverter* converter,
  100.        const char** source,
  101.        const char* sourceLimit,
  102.        UErrorCode* err);
  103. void T_UConverter_fromCodepageToCodepage (UConverter * outConverter,
  104.  UConverter * inConverter,
  105.  char **target,
  106.  const char *targetLimit,
  107.  const char **source,
  108.  const char *sourceLimit,
  109.  int32_t* offsets,
  110.  int flush,
  111.  UErrorCode * err);
  112. void Converter_fromUnicode(UConverter * _this,
  113.  char **target,
  114.  const char *targetLimit,
  115.  const UChar ** source,
  116.  const UChar * sourceLimit,
  117.  int32_t *offsets,
  118.  int flush,
  119.  UErrorCode * err);
  120. /*Calls through createConverter */
  121. UConverter* ucnv_open (const char *name,
  122.        UErrorCode * err)
  123. {
  124.   if (U_FAILURE (*err))
  125.     return NULL;
  126.   /*In case "name" is NULL we want to open the default converter */
  127.   if (name != NULL)
  128.     return createConverter (name, err);
  129.   else
  130.     return createConverter (iconv_getDefaultCodepage(), err);
  131. }
  132. /*Extracts the UChar* to a char* and calls through createConverter */
  133. UConverter*  ucnv_openU (const UChar * name,
  134.  UErrorCode * err)
  135. {
  136.   char asciiName[MAX_CONVERTER_NAME_LENGTH];
  137.   if (U_FAILURE (*err))
  138.     return NULL;
  139.   if (name == NULL)
  140.     return ucnv_open (NULL, err);
  141.   if (u_strlen (name) > MAX_CONVERTER_NAME_LENGTH)
  142.     {
  143.       *err = U_ILLEGAL_ARGUMENT_ERROR;
  144.       return NULL;
  145.     }
  146.   return ucnv_open (u_austrcpy (asciiName, name), err);
  147. }
  148. /*Decreases the reference counter in the shared immutable section of the object
  149.  *and frees the mutable part*/
  150. void ucnv_close (UConverter * converter)
  151. {
  152. /* for iconv we will close the handles and free the converter storage*/
  153.   iconv_close(converter->sharedData->toiconv_handle);
  154.   iconv_close(converter->sharedData->fromiconv_handle);
  155.   if (converter == NULL)
  156.     return;
  157.   free (converter);
  158.   return;
  159. }
  160. /* currently required for iconv suuport */
  161. /* XMLReader calls this and uses fact that it is different than min
  162. to go thru a calculation otherwise if max and min same then there is
  163. a calculation speed up - we will keep the two routines but have them
  164. return different sizes - later will ifdef XMLreader for ICONV to remove the calls*/
  165.  int8_t  ucnv_getMaxCharSize (const UConverter * converter)
  166. {
  167.   return (4); /* dummy returns just need to be different in XMLParser - need something else for ICU replacement */
  168. }
  169. /* currently required for iconv support */
  170. /* see note for ucnv_getMaxCharSize */
  171. int8_t  ucnv_getMinCharSize (const UConverter * converter)
  172. {
  173.   return (1);
  174. }
  175. void   ucnv_fromUnicode (UConverter * _this,
  176.  char **target,
  177.  const char *targetLimit,
  178.  const UChar ** source,
  179.  const UChar * sourceLimit,
  180.  int32_t* offsets,
  181.  int flush,
  182.  UErrorCode * err)
  183. {
  184.   /*
  185.    * Check parameters in for all conversions
  186.    */
  187.   if (U_FAILURE (*err))   return;
  188.   if ((_this == NULL) || ((char *) targetLimit < *target) || (sourceLimit < *source))
  189.     {
  190.       *err = U_ILLEGAL_ARGUMENT_ERROR;
  191.       return;
  192.     }
  193.   /*calls the specific conversion routines */
  194.   Converter_fromUnicode(_this,target,targetLimit,source,sourceLimit,
  195.    offsets,flush,err);
  196.   return;
  197. }
  198. void   ucnv_toUnicode (UConverter * _this,
  199.        UChar ** target,
  200.        const UChar * targetLimit,
  201.        const char **source,
  202.        const char *sourceLimit,
  203.        int32_t* offsets,
  204.        int flush,
  205.        UErrorCode * err)
  206. {
  207.   /*
  208.    * Check parameters in for all conversions
  209.    */
  210.   if (U_FAILURE (*err))   return;
  211.   if ((_this == NULL) || ((UChar *) targetLimit < *target) || (sourceLimit < *source))
  212.     {
  213.       *err = U_ILLEGAL_ARGUMENT_ERROR;
  214.       return;
  215.     }
  216.   /*calls the specific conversion routines */
  217.   Convert_toUnicode(_this,target,targetLimit,source,sourceLimit,
  218.   offsets,flush,err);
  219.   return;
  220. }
  221. int32_t   ucnv_fromUChars (const UConverter * converter,
  222.    char *target,
  223.    int32_t targetSize,
  224.    const UChar * source,
  225.    UErrorCode * err)
  226. {
  227.   const UChar *mySource = source;
  228.   const UChar *mySource_limit;
  229.   int32_t mySourceLength = 0;
  230.   UConverter myConverter;
  231.   char *myTarget = target;
  232.   int32_t targetCapacity = 0;
  233.   if (U_FAILURE (*err))
  234.     return 0;
  235.   if ((converter == NULL) || (targetSize < 0))
  236.     {
  237.       *err = U_ILLEGAL_ARGUMENT_ERROR;
  238.       return 0;
  239.     }
  240.   /*makes a local copy of the UConverter */
  241.   myConverter = *converter;
  242.   /*if the source is empty we return immediately */
  243.   mySourceLength = u_strlen (source);
  244.   if (mySourceLength == 0)
  245.     {
  246.       /*for consistency we still need to
  247.        *store 0 in the targetCapacity
  248.        *if the user requires it
  249.        */
  250.       return 0;
  251.     }
  252.   mySource_limit = mySource + mySourceLength;
  253.   if (targetSize > 0)
  254.     {
  255.       ucnv_fromUnicode (&myConverter,
  256. &myTarget,
  257. target + targetSize,
  258. &mySource,
  259. mySource_limit,
  260. NULL,
  261. TRUE,
  262. err);
  263.       targetCapacity = myTarget - target;
  264.     }
  265.   /*Updates targetCapacity to contain the number of bytes written to target */
  266.   if (targetSize == 0)
  267.     {
  268.       *err = U_BUFFER_OVERFLOW_ERROR;
  269.     }
  270.   /* If the output buffer is exhausted, we need to stop writing
  271.    * to it but continue the conversion in order to store in targetSize
  272.    * the number of bytes that was required*/
  273.   if (*err == U_BUFFER_OVERFLOW_ERROR)
  274.     {
  275.       char target2[CHUNK_SIZE];
  276.       char *target2_alias = target2;
  277.       const char *target2_limit = target2 + CHUNK_SIZE;
  278.       /*We use a stack allocated buffer around which we loop
  279.        *(in case the output is greater than CHUNK_SIZE)
  280.        */
  281.       while (*err == U_BUFFER_OVERFLOW_ERROR)
  282. {
  283.   *err = U_ZERO_ERROR;
  284.   target2_alias = target2;
  285.   ucnv_fromUnicode (&myConverter,
  286.     &target2_alias,
  287.     target2_limit,
  288.     &mySource,
  289.     mySource_limit,
  290.     NULL,
  291.     TRUE,
  292.     err);
  293.   /*updates the output parameter to contain the number of char required */
  294.   targetCapacity += (target2_alias - target2) + 1;
  295. }
  296.       /*We will set the erro code to BUFFER_OVERFLOW_ERROR only if
  297.        *nothing graver happened in the previous loop*/
  298.       (targetCapacity)--;
  299.       if (U_SUCCESS (*err))
  300. *err = U_BUFFER_OVERFLOW_ERROR;
  301.     }
  302.   return targetCapacity;
  303. }
  304. int32_t ucnv_toUChars (const UConverter * converter,
  305.        UChar * target,
  306.        int32_t targetSize,
  307.        const char *source,
  308.        int32_t sourceSize,
  309.        UErrorCode * err)
  310. {
  311.   const char *mySource = source;
  312.   const char *mySource_limit = source + sourceSize;
  313.   UConverter myConverter;
  314.   UChar *myTarget = target;
  315.   int32_t targetCapacity;
  316.   if (U_FAILURE (*err))
  317.     return 0;
  318.   if ((converter == NULL) || (targetSize < 0) || (sourceSize < 0))
  319.     {
  320.       *err = U_ILLEGAL_ARGUMENT_ERROR;
  321.       return 0;
  322.     }
  323.   /*Means there is no work to be done */
  324.   if (sourceSize == 0)
  325.     {
  326.       /*for consistency we still need to
  327.        *store 0 in the targetCapacity
  328.        *if the user requires it
  329.        */
  330.       if (targetSize >= 1)
  331. {
  332.   target[0] = 0x0000;
  333.   return 1;
  334. }
  335.       else
  336. return 0;
  337.     }
  338.   /*makes a local copy of the UConverter */
  339.   myConverter = *converter;
  340.   /*Not in pure pre-flight mode */
  341.   if (targetSize > 0)
  342.     {
  343.      /*  Changed from (targetSize * 2) to (targetSize) */
  344.       ucnv_toUnicode (&myConverter,
  345.       &myTarget,
  346.       target + (targetSize-1),   /*Save a spot for the Null terminator */
  347.       &mySource,
  348.       mySource_limit,
  349.       NULL,
  350.       TRUE,
  351.       err);
  352.       /*Null terminates the string */
  353.       *(myTarget) = 0x0000;
  354.     }
  355.   /*Rigs targetCapacity to have at least one cell for zero termination */
  356.   /*Updates targetCapacity to contain the number of bytes written to target */
  357.   targetCapacity = 1;
  358.   targetCapacity += myTarget - target;
  359.   if (targetSize == 0)
  360.     {
  361.       *err = U_BUFFER_OVERFLOW_ERROR;
  362.     }
  363.   /* If the output buffer is exhausted, we need to stop writing
  364.    * to it but if the input buffer is not exhausted,
  365.    * we need to continue the conversion in order to store in targetSize
  366.    * the number of bytes that was required
  367.    */
  368.   if (*err == U_BUFFER_OVERFLOW_ERROR)
  369.     {
  370.       UChar target2[CHUNK_SIZE];
  371.       UChar *target2_alias = target2;
  372.       const UChar *target2_limit = target2 + CHUNK_SIZE;
  373.       /*We use a stack allocated buffer around which we loop
  374.          (in case the output is greater than CHUNK_SIZE) */
  375.       while (*err == U_BUFFER_OVERFLOW_ERROR)
  376. {
  377.   *err = U_ZERO_ERROR;
  378.   target2_alias = target2;
  379.   ucnv_toUnicode (&myConverter,
  380.   &target2_alias,
  381.   target2_limit,
  382.   &mySource,
  383.   mySource_limit,
  384.   NULL,
  385.   TRUE,
  386.   err);
  387.   /*updates the output parameter to contain the number of char required */
  388.   targetCapacity += target2_alias - target2 + 1;
  389. }
  390.       (targetCapacity)--; /*adjust for last one */
  391.       if (U_SUCCESS (*err))
  392. *err = U_BUFFER_OVERFLOW_ERROR;
  393.     }
  394.   return targetCapacity;
  395. }
  396. UChar ucnv_getNextUChar (UConverter * converter,
  397.  const char **source,
  398.  const char *sourceLimit,
  399.  UErrorCode * err)
  400. {
  401.   /*calls the specific conversion routines */
  402.   /*as dictated in a code review, avoids a switch statement */
  403.   return getNextUChar(converter,source,sourceLimit,err);
  404. }
  405. /**************************
  406. * Will convert a sequence of bytes from one codepage to another.
  407. * @param toConverterName: The name of the converter that will be used to encode the output buffer
  408. * @param fromConverterName: The name of the converter that will be used to decode the input buffer
  409. * @param target: Pointer to the output buffer* written
  410. * @param targetLength: on input contains the capacity of target, on output the number of bytes copied to target
  411. * @param source: Pointer to the input buffer
  412. * @param sourceLength: on input contains the capacity of source, on output the number of bytes processed in "source"
  413. * @param internal: used internally to store store state data across calls
  414. * @param err: fills in an error status
  415. */
  416. void
  417. T_UConverter_fromCodepageToCodepage (UConverter * outConverter,
  418.      UConverter * inConverter,
  419.      char **target,
  420.      const char *targetLimit,
  421.      const char **source,
  422.      const char *sourceLimit,
  423.      int32_t* offsets,
  424.      int flush,
  425.      UErrorCode * err)
  426. {
  427.   UChar out_chunk[CHUNK_SIZE];
  428.   const UChar *out_chunk_limit = out_chunk + CHUNK_SIZE;
  429.   UChar *out_chunk_alias;
  430.   UChar const *out_chunk_alias2;
  431.   if (U_FAILURE (*err))    return;
  432.   /*loops until the input buffer is completely consumed
  433.    *or if an error has be encountered
  434.    *first we convert from inConverter codepage to Unicode
  435.    *then from Unicode to outConverter codepage
  436.    */
  437.   while ((*source != sourceLimit) && U_SUCCESS (*err))
  438.     {
  439.       out_chunk_alias = out_chunk;
  440.       ucnv_toUnicode (inConverter,
  441.       &out_chunk_alias,
  442.       out_chunk_limit,
  443.       source,
  444.       sourceLimit,
  445.       NULL,
  446.       flush,
  447.       err);
  448.       /*BUFFER_OVERFLOW_ERROR means that the output "CHUNK" is full
  449.        *we will require at least another loop (it's a recoverable error)
  450.        */
  451.       if (U_SUCCESS (*err) || (*err == U_BUFFER_OVERFLOW_ERROR))
  452. {
  453.   *err = U_ZERO_ERROR;
  454.   out_chunk_alias2 = out_chunk;
  455.   while ((out_chunk_alias2 != out_chunk_alias) && U_SUCCESS (*err))
  456.     {
  457.       ucnv_fromUnicode (outConverter,
  458. target,
  459. targetLimit,
  460. &out_chunk_alias2,
  461. out_chunk_alias,
  462. NULL,
  463. TRUE,
  464. err);
  465.     }
  466. }
  467.       else
  468. break;
  469.     }
  470.   return;
  471. }
  472. int32_t  ucnv_convert(const char *toConverterName,
  473.       const char *fromConverterName,
  474.       char *target,
  475.       int32_t targetSize,
  476.       const char *source,
  477.       int32_t sourceSize,
  478.       UErrorCode * err)
  479. {
  480.   const char *mySource = source;
  481.   const char *mySource_limit = source + sourceSize;
  482.   int32_t mySourceLength = 0;
  483.   UConverter *inConverter;
  484.   UConverter *outConverter;
  485.   char *myTarget = target;
  486.   int32_t targetCapacity = 0;
  487.   if (U_FAILURE (*err))
  488.     return 0;
  489.   if ((targetSize < 0) || (sourceSize < 0))
  490.     {
  491.       *err = U_ILLEGAL_ARGUMENT_ERROR;
  492.       return 0;
  493.     }
  494.   /*if there is no input data, we're done */
  495.   if (sourceSize == 0)
  496.     {
  497.       /*in case the caller passed an output ptr
  498.        *we update it
  499.        */
  500.       return 0;
  501.     }
  502.   /*create the converters */
  503.   inConverter = ucnv_open (fromConverterName, err);
  504.   if (U_FAILURE (*err)) return 0;
  505.   outConverter = ucnv_open (toConverterName, err);
  506.   if (U_FAILURE (*err))
  507.     {
  508.       ucnv_close (inConverter);
  509.       return 0;
  510.     }
  511.   if (targetSize > 0)
  512.     {
  513.       T_UConverter_fromCodepageToCodepage (outConverter,
  514.    inConverter,
  515.    &myTarget,
  516.    target + targetSize,
  517.    &mySource,
  518.    mySource_limit,
  519.    NULL,
  520.    TRUE,
  521.    err);
  522.     }
  523.   /*Updates targetCapacity to contain the number of bytes written to target */
  524.   targetCapacity = myTarget - target;
  525.   if (targetSize == 0)
  526.     {
  527.       *err = U_BUFFER_OVERFLOW_ERROR;
  528.     }
  529.   /* If the output buffer is exhausted, we need to stop writing
  530.    * to it but continue the conversion in order to store in targetSize
  531.    * the number of bytes that was required*/
  532.   if (*err == U_BUFFER_OVERFLOW_ERROR)
  533.     {
  534.       char target2[CHUNK_SIZE];
  535.       char *target2_alias = target2;
  536.       const char *target2_limit = target2 + CHUNK_SIZE;
  537.       /*We use a stack allocated buffer around which we loop
  538.        *(in case the output is greater than CHUNK_SIZE)
  539.        */
  540.       while (*err == U_BUFFER_OVERFLOW_ERROR)
  541. {
  542.   *err = U_ZERO_ERROR;
  543.   target2_alias = target2;
  544.   T_UConverter_fromCodepageToCodepage (outConverter,
  545.        inConverter,
  546.        &target2_alias,
  547.        target2_limit,
  548.        &mySource,
  549.        mySource_limit,
  550.        NULL,
  551.        TRUE,
  552.        err);
  553.   /*updates the output parameter to contain the number of char required */
  554.   targetCapacity += (target2_alias - target2) + 1;
  555. }
  556.       /*We will set the erro code to BUFFER_OVERFLOW_ERROR only if
  557.        *nothing graver happened in the previous loop*/
  558.       (targetCapacity)--;
  559.       if (U_SUCCESS (*err))
  560. *err = U_BUFFER_OVERFLOW_ERROR;
  561.     }
  562.   ucnv_close (inConverter);
  563.   ucnv_close (outConverter);
  564.   return targetCapacity;
  565. }
  566. void Converter_fromUnicode(UConverter * _this,
  567.  char **target,
  568.  const char *targetLimit,
  569.  const UChar ** source,
  570.  const UChar * sourceLimit,
  571.  int32_t *offsets,
  572.  int flush,
  573.  UErrorCode * err)
  574. {
  575.   int chardone;
  576.   const UChar *mySource = *source;
  577.   unsigned char *myTarget = (unsigned char *) *target;
  578.   int32_t targetLength = targetLimit - (char *) myTarget;
  579.   int32_t sourceLength = (sourceLimit - mySource) * 2;
  580.   unsigned char targetChar = 0x00;
  581.   /* pick up the iconv handle and perform the conversion */
  582.   errno = 0;
  583.   chardone =iconv(_this->sharedData->fromiconv_handle,(char**)source,  (size_t*) &sourceLength,target,(size_t *)&targetLength);
  584.   if (errno!=0)
  585.     if (errno == E2BIG)
  586.       {
  587.   *err = U_BUFFER_OVERFLOW_ERROR;
  588.           return;
  589.       }
  590.     else
  591.       if ((errno ==EBADDATA)|| (errno ==ECONVERT))
  592.        {
  593.         char errno_id[7];
  594.         send_message(NULL,ICONV_CONVERT_PROBLEM,'d');
  595.         convert_errno(errno_id,errno);
  596.         send_message(NULL,errno_id,'d');
  597.         *err = U_INVALID_CHAR_FOUND;
  598. return;
  599. }
  600.   return;
  601.        }
  602. void Convert_toUnicode(UConverter * _this,
  603.   UChar ** target,
  604.   const UChar * targetLimit,
  605.   const char **source,
  606.   const char *sourceLimit,
  607.   int32_t *offsets,
  608.   int flush,
  609.   UErrorCode * err)
  610. {
  611.   char *mySource = (char *) *source;
  612.   UChar *myTarget = *target;
  613.   int32_t targetLength = (targetLimit - myTarget)*2;  /* multiply by 2 */
  614.   int32_t sourceLength = (sourceLimit - (char *) mySource);
  615.   int chardone;
  616.   /* pick up the iconv handle */
  617.   errno = 0;
  618.   chardone =iconv(_this->sharedData->toiconv_handle,(char**)source,  (size_t*) &sourceLength,(char **)target,(size_t *)&targetLength);
  619.   if (errno!=0)
  620.   {
  621.     if (errno == E2BIG)
  622.       {
  623.   *err = U_BUFFER_OVERFLOW_ERROR;
  624.           return;
  625.       }
  626.     else
  627.       if ((errno ==EBADDATA)|| (errno ==ECONVERT))
  628.        {
  629.         char errno_id[7];
  630.         send_message(NULL,ICONV_CONVERT_PROBLEM,'d');
  631.         convert_errno(errno_id,errno);
  632.         send_message(NULL,errno_id,'d');
  633.         *err = U_INVALID_CHAR_FOUND;
  634.         return;
  635. }
  636. }
  637.   return;
  638. }
  639. UChar getNextUChar(UConverter* converter,
  640.        const char** source,
  641.        const char* sourceLimit,
  642.        UErrorCode* err)
  643. {
  644.   UChar myUChar;
  645.   UChar* myUCharptr;
  646.   size_t numberibytes=sizeof(UChar);
  647.   size_t numberobytes=sizeof(UChar);
  648.   int chardone;
  649.   if ((*source)+1 > sourceLimit)
  650.     {
  651.       *err = U_INDEX_OUTOFBOUNDS_ERROR;
  652.       return 0xFFFD;
  653.     }
  654.   /*pick up the iconv handle */
  655.   /* convert the requested character - need to cache characters 6 will do - XMLReader is using this function to get header to process*/
  656.   myUCharptr  = &myUChar;
  657.  chardone =iconv(converter->sharedData->toiconv_handle,(char**)source,  (size_t*) &numberibytes,(char **)&myUCharptr,(size_t *)&numberobytes);
  658.   if (myUChar != 0xFFFD) return myUChar;
  659.   else
  660.     {
  661.       UChar* myUCharPtr = &myUChar;
  662.       const char* sourceFinal = *source;
  663.       *err = U_INVALID_CHAR_FOUND;
  664.       /*makes the internal caching transparent to the user*/
  665.       if (*err == U_INDEX_OUTOFBOUNDS_ERROR) *err = U_ZERO_ERROR;
  666.       return myUChar;
  667.     }
  668. }