home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / common / ucnv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-11  |  29.3 KB  |  1,163 lines

  1. /*
  2.    ********************************************************************************
  3.    *                                                                              *
  4.    * COPYRIGHT:                                                                   *
  5.    *   (C) Copyright International Business Machines Corporation, 1998            *
  6.    *   Licensed Material - Program-Property of IBM - All Rights Reserved.         *
  7.    *   US Government Users Restricted Rights - Use, duplication, or disclosure    *
  8.    *   restricted by GSA ADP Schedule Contract with IBM Corp.                     *
  9.    *                                                                              *
  10.    ********************************************************************************
  11.    *
  12.    *
  13.    *  ucnv.c:
  14.    *  Implements APIs for the ICU's codeset conversion library
  15.    *  mostly calls through internal functions created and maintained 
  16.    *  by Bertrand A. Damiba
  17.    *
  18.    * Modification History:
  19.    *
  20.    *   Date        Name        Description
  21.    *   04/04/99    helena      Fixed internal header inclusion.
  22.  */
  23. #include "umutex.h"
  24. #include "ures.h"
  25. #include "uhash.h"
  26. #include "ucmp16.h"
  27. #include "ucmp8.h"
  28. #include "ucnv_bld.h"
  29. #include "ucnv_io.h"
  30. #include "ucnv_err.h"
  31. #include "ucnv_cnv.h"
  32. #include "ucnv_imp.h"
  33. #include "ucnv.h"
  34. #include "cmemory.h"
  35. #include "cstring.h"
  36. #include "ustring.h"
  37. #include "uloc.h"
  38.  
  39. #define CHUNK_SIZE 5*1024
  40.  
  41.  
  42. typedef void (*T_ToUnicodeFunction) (UConverter *,
  43.                      UChar **,
  44.                      const UChar *,
  45.                      const char **,
  46.                      const char *,
  47.                      int32_t* offsets,
  48.                      bool_t,
  49.                      UErrorCode *);
  50.  
  51. typedef void (*T_FromUnicodeFunction) (UConverter *,
  52.                        char **,
  53.                        const char *,
  54.                        const UChar **,
  55.                        const UChar *,
  56.                        int32_t* offsets,
  57.                        bool_t,
  58.                        UErrorCode *);
  59.  
  60. typedef UChar (*T_GetNextUCharFunction) (UConverter *,
  61.                      const char **,
  62.                      const char *,
  63.                      UErrorCode *);
  64.  
  65. static T_ToUnicodeFunction TO_UNICODE_FUNCTIONS[UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES] =
  66.  
  67. {
  68.   T_UConverter_toUnicode_SBCS,
  69.   T_UConverter_toUnicode_DBCS,
  70.   T_UConverter_toUnicode_MBCS,
  71.   T_UConverter_toUnicode_LATIN_1,
  72.   T_UConverter_toUnicode_UTF8,
  73.   T_UConverter_toUnicode_UTF16_BE,
  74.   T_UConverter_toUnicode_UTF16_LE,
  75.   T_UConverter_toUnicode_EBCDIC_STATEFUL,
  76.   T_UConverter_toUnicode_ISO_2022
  77. };
  78.  
  79. static T_ToUnicodeFunction TO_UNICODE_FUNCTIONS_OFFSETS_LOGIC[UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES] =
  80.  
  81. {
  82.   NULL, /*UCNV_SBCS*/
  83.   NULL, /*UCNV_DBCS*/
  84.   T_UConverter_toUnicode_MBCS_OFFSETS_LOGIC,
  85.   NULL, /*UCNV_LATIN_1*/
  86.   T_UConverter_toUnicode_UTF8_OFFSETS_LOGIC,
  87.   NULL, /*UTF16_BE*/
  88.   NULL, /*UTF16_LE*/
  89.   T_UConverter_toUnicode_EBCDIC_STATEFUL_OFFSETS_LOGIC,
  90.   T_UConverter_toUnicode_ISO_2022_OFFSETS_LOGIC
  91. };
  92.  
  93. static T_FromUnicodeFunction FROM_UNICODE_FUNCTIONS_OFFSETS_LOGIC[UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES] =
  94.  
  95. {
  96.   NULL, /*UCNV_SBCS*/
  97.   NULL, /*UCNV_DBCS*/
  98.   T_UConverter_fromUnicode_MBCS_OFFSETS_LOGIC,
  99.   NULL, /*UCNV_LATIN_1*/
  100.   T_UConverter_fromUnicode_UTF8_OFFSETS_LOGIC,
  101.   NULL, /*UTF16_BE*/
  102.   NULL, /*UTF16_LE*/
  103.   T_UConverter_fromUnicode_EBCDIC_STATEFUL_OFFSETS_LOGIC,
  104.   T_UConverter_fromUnicode_ISO_2022_OFFSETS_LOGIC
  105. };
  106.  
  107. static T_FromUnicodeFunction FROM_UNICODE_FUNCTIONS[UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES] =
  108. {
  109.   T_UConverter_fromUnicode_SBCS,
  110.   T_UConverter_fromUnicode_DBCS,
  111.   T_UConverter_fromUnicode_MBCS,
  112.   T_UConverter_fromUnicode_LATIN_1,
  113.   T_UConverter_fromUnicode_UTF8,
  114.   T_UConverter_fromUnicode_UTF16_BE,
  115.   T_UConverter_fromUnicode_UTF16_LE,
  116.   T_UConverter_fromUnicode_EBCDIC_STATEFUL,
  117.   T_UConverter_fromUnicode_ISO_2022
  118. };
  119.  
  120. static T_GetNextUCharFunction GET_NEXT_UChar_FUNCTIONS[UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES] =
  121. {
  122.   T_UConverter_getNextUChar_SBCS,
  123.   T_UConverter_getNextUChar_DBCS,
  124.   T_UConverter_getNextUChar_MBCS,
  125.   T_UConverter_getNextUChar_LATIN_1,
  126.   T_UConverter_getNextUChar_UTF8,
  127.   T_UConverter_getNextUChar_UTF16_BE,
  128.   T_UConverter_getNextUChar_UTF16_LE,
  129.   T_UConverter_getNextUChar_EBCDIC_STATEFUL,
  130.   T_UConverter_getNextUChar_ISO_2022
  131. };
  132.  
  133.  
  134. void flushInternalUnicodeBuffer (UConverter * _this,
  135.                  UChar * myTarget,
  136.                  int32_t * myTargetIndex,
  137.                  int32_t targetLength,
  138.                  int32_t** offsets,
  139.                  UErrorCode * err);
  140.  
  141. void flushInternalCharBuffer (UConverter * _this,
  142.                   char *myTarget,
  143.                   int32_t * myTargetIndex,
  144.                   int32_t targetLength,
  145.                   int32_t** offsets,
  146.                   UErrorCode * err);
  147.  
  148.  
  149. static void T_UConverter_fromCodepageToCodepage (UConverter * outConverter,
  150.                          UConverter * inConverter,
  151.                          char **target,
  152.                          const char *targetLimit,
  153.                          const char **source,
  154.                          const char *sourceLimit,
  155.                          int32_t* offsets,
  156.                          bool_t flush,
  157.                          UErrorCode * err);
  158.  
  159.  
  160. const char* ucnv_getDefaultName ()
  161. {
  162.   return icu_getDefaultCodepage();
  163. }
  164.  
  165. void   ucnv_setDefaultName (const char *converterName)
  166. {
  167.   icu_strcpy ((char*)icu_getDefaultCodepage(), converterName);
  168. }
  169. /*Calls through createConverter */
  170. UConverter* ucnv_open (const char *name,
  171.                UErrorCode * err)
  172. {
  173.   if (U_FAILURE (*err))
  174.     return NULL;
  175.  
  176.   /*In case "name" is NULL we want to open the default converter */
  177.   if (name != NULL)
  178.     return createConverter (name, err);
  179.   else
  180.     return createConverter (icu_getDefaultCodepage(), err);
  181. }
  182.  
  183. /*Extracts the UChar* to a char* and calls through createConverter */
  184. UConverter*  ucnv_openU (const UChar * name,
  185.              UErrorCode * err)
  186. {
  187.   char asciiName[UCNV_MAX_CONVERTER_NAME_LENGTH];
  188.   
  189.   if (U_FAILURE (*err))
  190.     return NULL;
  191.   if (name == NULL)
  192.     return ucnv_open (NULL, err);
  193.   if (u_strlen (name) > UCNV_MAX_CONVERTER_NAME_LENGTH)
  194.     {
  195.       *err = U_ILLEGAL_ARGUMENT_ERROR;
  196.       return NULL;
  197.     }
  198.   return ucnv_open (u_austrcpy (asciiName, name), err);
  199. }
  200.  
  201. /*Assumes a $platform-#codepage.$CONVERTER_FILE_EXTENSION scheme and calls
  202.  *through createConverter*/
  203. UConverter*  ucnv_openCCSID (int32_t codepage,
  204.                  UConverterPlatform platform,
  205.                  UErrorCode * err)
  206. {
  207.   char myName[UCNV_MAX_CONVERTER_NAME_LENGTH];
  208.  
  209.   if (U_FAILURE (*err))
  210.     return NULL;
  211.  
  212.   copyPlatformString (myName, platform);
  213.   icu_strcat (myName, "-");
  214.   T_CString_integerToString (myName + icu_strlen (myName), codepage, 10);
  215.  
  216.  
  217.   return createConverter (myName, err);
  218. }
  219.  
  220. /*Decreases the reference counter in the shared immutable section of the object
  221.  *and frees the mutable part*/
  222.  
  223. void ucnv_close (UConverter * converter)
  224. {
  225.   if (converter == NULL)
  226.     return;
  227.   if ((converter->sharedData->conversionType == UCNV_ISO_2022) &&
  228.       (converter->mode == UCNV_SO))
  229.     {
  230.       ucnv_close (((UConverterDataISO2022 *) (converter->extraInfo))->currentConverter);
  231.       icu_free (converter->extraInfo);
  232.     }
  233.  
  234.   umtx_lock (NULL);
  235.   converter->sharedData->referenceCounter--;
  236.   umtx_unlock (NULL);
  237.   icu_free (converter);
  238.  
  239.   return;
  240. }
  241.  
  242. /*Frees all shared immutable objects that aren't referred to (reference count = 0)
  243.  */
  244. int32_t  ucnv_flushCache ()
  245. {
  246.   UConverterSharedData *mySharedData = NULL;
  247.   int32_t pos = -1;
  248.   int32_t tableDeletedNum = 0;
  249.  
  250.   /*if shared data hasn't even been lazy evaluated yet
  251.    * return 0
  252.    */
  253.   if (SHARED_DATA_HASHTABLE == NULL)
  254.     return 0;
  255.  
  256.   /*creates an enumeration to iterate through every element in the
  257.    *table
  258.    */
  259.   umtx_lock (NULL);
  260.   while (mySharedData = (UConverterSharedData *) uhash_nextElement (SHARED_DATA_HASHTABLE, &pos))
  261.     {
  262.       /*deletes only if reference counter == 0 */
  263.       if (mySharedData->referenceCounter == 0)
  264.     {
  265.       UErrorCode err = U_ZERO_ERROR;
  266.       tableDeletedNum++;
  267.  
  268.       uhash_remove (SHARED_DATA_HASHTABLE, uhash_hashIString (mySharedData->name), &err);
  269.       deleteSharedConverterData (mySharedData);
  270.  
  271.     }
  272.     }
  273.   umtx_unlock (NULL);
  274.  
  275.   return tableDeletedNum;
  276. }
  277.  
  278. /*returns a single Name from the static list, will return NULL if out of bounds
  279.  */
  280. const char*  ucnv_getAvailableName (int32_t index)
  281. {
  282.   UErrorCode err = U_ZERO_ERROR;
  283.   /*lazy evaluates the list of Available converters */
  284.   if (AVAILABLE_CONVERTERS_NAMES == NULL)
  285.     setupAliasTableAndAvailableConverters (&err);
  286.   if (index > AVAILABLE_CONVERTERS)
  287.     return NULL;
  288.   else
  289.     return AVAILABLE_CONVERTERS_NAMES[index];
  290. }
  291.  
  292. int32_t  ucnv_countAvailable ()
  293. {
  294.   UErrorCode err = U_ZERO_ERROR;
  295.   /*lazy evaluates the list of Available converters */
  296.   if (AVAILABLE_CONVERTERS_NAMES == NULL)
  297.     setupAliasTableAndAvailableConverters (&err);
  298.  
  299.   return AVAILABLE_CONVERTERS;
  300. }
  301.  
  302. void   ucnv_getSubstChars (const UConverter * converter,
  303.                char *mySubChar,
  304.                int8_t * len,
  305.                UErrorCode * err)
  306. {
  307.   if (U_FAILURE (*err))
  308.     return;
  309.  
  310.   if (*len < converter->subCharLen)    /*not enough space in subChars */
  311.     {
  312.       *err = U_INDEX_OUTOFBOUNDS_ERROR;
  313.       return;
  314.     }
  315.  
  316.   icu_memcpy (mySubChar, converter->subChar, converter->subCharLen);    /*fills in the subchars */
  317.   *len = converter->subCharLen;    /*store # of bytes copied to buffer */
  318.  
  319.   return;
  320. }
  321.  
  322. void   ucnv_setSubstChars (UConverter * converter,
  323.                const char *mySubChar,
  324.                int8_t len,
  325.                UErrorCode * err)
  326. {
  327.   uint8_t x = 0;
  328.  
  329.   if (U_FAILURE (*err))
  330.     return;
  331.  
  332.   /*Makes sure that the subChar is within the codepages char length boundaries */
  333.   if ((len > converter->sharedData->maxBytesPerChar)
  334.       || (len < converter->sharedData->minBytesPerChar))
  335.     {
  336.       *err = U_ILLEGAL_ARGUMENT_ERROR;
  337.       return;
  338.     }
  339.  
  340.   icu_memcpy (converter->subChar, mySubChar, len);    /*copies the subchars */
  341.   converter->subCharLen = len;    /*sets the new len */
  342.  
  343.   return;
  344. }
  345.  
  346.  
  347.  
  348.  
  349. int32_t  ucnv_getDisplayName (const UConverter * converter,
  350.                   const char *displayLocale,
  351.                   UChar * displayName,
  352.                   int32_t displayNameCapacity,
  353.                   UErrorCode * err)
  354. {
  355.   UChar stringToWriteBuffer[UCNV_MAX_CONVERTER_NAME_LENGTH];
  356.   UChar const *stringToWrite;
  357.   int32_t stringToWriteLength;
  358.   UResourceBundle *rb = NULL;
  359.  
  360.   if (U_FAILURE (*err))
  361.     return 0;
  362.  
  363.   /*create an RB, init the fill-in string, gets it from the RB */
  364.   rb = ures_open (NULL, displayLocale, err);
  365.  
  366.   stringToWrite = ures_get (rb,
  367.                 converter->sharedData->name,
  368.                 err);
  369.  
  370.   if (rb)
  371.     ures_close (rb);
  372.  
  373.   if (U_SUCCESS (*err))
  374.     stringToWriteLength = u_strlen (stringToWrite);
  375.   else
  376.     {
  377.       /*Error While creating or getting resource from the resource bundle
  378.        *use the internal name instead
  379.        *
  380.        *sets stringToWriteLength (which accounts for a NULL terminator)
  381.        *and stringToWrite
  382.        */
  383.       stringToWriteLength = icu_strlen (converter->sharedData->name) + 1;
  384.       stringToWrite = u_uastrcpy (stringToWriteBuffer, converter->sharedData->name);
  385.  
  386.       /*Hides the fallback to the internal name from the user */
  387.       if (*err == U_MISSING_RESOURCE_ERROR)
  388.     *err = U_ZERO_ERROR;
  389.     }
  390.  
  391.   /*At this point we have a displayName and its length
  392.    *we want to see if it fits in the user provided params
  393.    */
  394.  
  395.   if (stringToWriteLength <= displayNameCapacity)
  396.     {
  397.       /*it fits */
  398.       u_strcpy (displayName, stringToWrite);
  399.     }
  400.   else
  401.     {
  402.       /*it doesn't fit */
  403.       *err = U_BUFFER_OVERFLOW_ERROR;
  404.  
  405.       u_strncpy (displayName,
  406.          stringToWrite,
  407.          displayNameCapacity);
  408.       /*Zero terminates the string */
  409.       if (displayNameCapacity > 0)
  410.     displayName[displayNameCapacity - 1] = 0x0000;
  411.     }
  412.  
  413.   /*if the user provided us with a with an outputLength
  414.    *buffer we'll store in it the theoretical size of the
  415.    *displayString
  416.    */
  417.   return stringToWriteLength;
  418. }
  419.  
  420.  
  421. /*resets the internal states of a converter
  422.  *goal : have the same behaviour than a freshly created converter
  423.  */
  424. void  ucnv_reset (UConverter * converter)
  425. {
  426.   converter->toUnicodeStatus = converter->sharedData->defaultConverterValues.toUnicodeStatus;
  427.   converter->fromUnicodeStatus = 0;
  428.   converter->UCharErrorBufferLength = 0;
  429.   converter->charErrorBufferLength = 0;
  430.   if ((converter->sharedData->conversionType == UCNV_ISO_2022) &&
  431.       (converter->mode == UCNV_SO))
  432.     {
  433.       converter->charErrorBufferLength = 3;
  434.       converter->charErrorBuffer[0] = 0x1b;
  435.       converter->charErrorBuffer[1] = 0x25;
  436.       converter->charErrorBuffer[2] = 0x42;
  437.       ucnv_close (((UConverterDataISO2022 *) (converter->extraInfo))->currentConverter);
  438.       ((UConverterDataISO2022 *) (converter->extraInfo))->currentConverter = NULL;
  439.       ((UConverterDataISO2022 *) (converter->extraInfo))->escSeq2022Length = 0;
  440.     }
  441.   converter->mode = UCNV_SI;
  442.  
  443.   return;
  444. }
  445.  
  446. int8_t  ucnv_getMaxCharSize (const UConverter * converter)
  447. {
  448.   return converter->sharedData->maxBytesPerChar;
  449. }
  450.  
  451.  
  452. int8_t  ucnv_getMinCharSize (const UConverter * converter)
  453. {
  454.   return converter->sharedData->minBytesPerChar;
  455. }
  456.  
  457. const char*  ucnv_getName (const UConverter * converter, UErrorCode * err)
  458.      
  459. {
  460.   if (U_FAILURE (*err))
  461.     return NULL;
  462.  
  463.   return converter->sharedData->name;
  464. }
  465.  
  466. int32_t  ucnv_getCCSID (const UConverter * converter,
  467.             UErrorCode * err)
  468. {
  469.   if (U_FAILURE (*err))
  470.     return -1;
  471.  
  472.   return converter->sharedData->codepage;
  473. }
  474.  
  475.  
  476. UConverterPlatform  ucnv_getPlatform (const UConverter * converter,
  477.                  UErrorCode * err)
  478. {
  479.   if (U_FAILURE (*err))
  480.     return UCNV_UNKNOWN;
  481.   
  482.   return converter->sharedData->platform;
  483. }
  484.  
  485. UConverterToUCallback  ucnv_getToUCallBack (const UConverter * converter)
  486. {
  487.   return converter->fromCharErrorBehaviour;
  488. }
  489.  
  490. UConverterFromUCallback  ucnv_getFromUCallBack (const UConverter * converter)
  491. {
  492.   return converter->fromUCharErrorBehaviour;
  493. }
  494.  
  495. UConverterToUCallback   ucnv_setToUCallBack (UConverter * converter,
  496.                     UConverterToUCallback action,
  497.                     UErrorCode * err)
  498. {
  499.   UConverterToUCallback myReturn = NULL;
  500.  
  501.   if (U_FAILURE (*err))
  502.     return NULL;
  503.   myReturn = converter->fromCharErrorBehaviour;
  504.   converter->fromCharErrorBehaviour = action;
  505.  
  506.   return myReturn;
  507. }
  508.  
  509. UConverterFromUCallback   ucnv_setFromUCallBack (UConverter * converter,
  510.                         UConverterFromUCallback action,
  511.                         UErrorCode * err)
  512. {
  513.   UConverterFromUCallback myReturn = NULL;
  514.   
  515.   if (U_FAILURE (*err))
  516.     return NULL;
  517.   myReturn = converter->fromUCharErrorBehaviour;
  518.   converter->fromUCharErrorBehaviour = action;
  519.  
  520.   return myReturn;
  521. }
  522. #include <stdio.h>
  523. void   ucnv_fromUnicode (UConverter * _this,
  524.              char **target,
  525.              const char *targetLimit,
  526.              const UChar ** source,
  527.              const UChar * sourceLimit,
  528.              int32_t* offsets,
  529.              bool_t flush,
  530.              UErrorCode * err)
  531. {
  532.   UConverterType myConvType;
  533.   /*
  534.    * Check parameters in for all conversions
  535.    */
  536.   if (U_FAILURE (*err))   return;
  537.   if ((_this == NULL) || ((char *) targetLimit < *target) || (sourceLimit < *source))
  538.     {
  539.       *err = U_ILLEGAL_ARGUMENT_ERROR;
  540.       return;
  541.     }
  542.   
  543.  
  544.   /*
  545.    * Deal with stored carry over data.  This is done in the common location
  546.    * to avoid doing it for each conversion.
  547.    */
  548.   if (_this->charErrorBufferLength > 0)
  549.     {
  550.       int32_t myTargetIndex = 0;
  551.  
  552.       flushInternalCharBuffer (_this, 
  553.                    (char *) *target,
  554.                    &myTargetIndex,
  555.                    targetLimit - *target,
  556.                    offsets?&offsets:NULL,
  557.                    err);
  558.       *target += myTargetIndex;
  559.       if (U_FAILURE (*err)) return;
  560.     }
  561.   
  562.   myConvType = _this->sharedData->conversionType;  
  563.   if (offsets) 
  564.     {
  565.        int32_t targetSize = targetLimit - *target;
  566.        int32_t i;
  567.        switch (myConvType)
  568.      {
  569.      case UCNV_LATIN_1: case UCNV_SBCS : 
  570.        {
  571.          for (i=0; i<targetSize; i++) offsets[i] = i;
  572.          break;
  573.        }
  574.      case UCNV_UTF16_LittleEndian: case UCNV_UTF16_BigEndian: case UCNV_DBCS: 
  575.        {
  576.          --targetSize;
  577.          for (i=0; i<targetSize; i+=2) 
  578.            {
  579.          offsets[i] = i;
  580.          offsets[i+1] = i;
  581.            }
  582.          break;
  583.        }
  584.      default:
  585.        {
  586.          
  587.          FROM_UNICODE_FUNCTIONS_OFFSETS_LOGIC[(int) myConvType] (_this,
  588.                                      target,
  589.                                      targetLimit,
  590.                                      source,
  591.                                      sourceLimit,
  592.                                      offsets,
  593.                                      flush,
  594.                                      err);
  595.          return;
  596.        }
  597.      };    
  598.     }
  599.   /*calls the specific conversion routines */
  600.   FROM_UNICODE_FUNCTIONS[(int)myConvType] (_this,
  601.                        target,
  602.                        targetLimit,
  603.                        source,
  604.                        sourceLimit,
  605.                        offsets,
  606.                        flush,
  607.                        err);
  608.   
  609.   return;
  610. }
  611.  
  612.  
  613.  
  614. void   ucnv_toUnicode (UConverter * _this,
  615.                UChar ** target,
  616.                const UChar * targetLimit,
  617.                const char **source,
  618.                const char *sourceLimit,
  619.                int32_t* offsets,
  620.                bool_t flush,
  621.                UErrorCode * err)
  622. {
  623.   /*
  624.    * Check parameters in for all conversions
  625.    */
  626.   UConverterType myConvType;
  627.   if (U_FAILURE (*err))   return;
  628.   if ((_this == NULL) || ((UChar *) targetLimit < *target) || (sourceLimit < *source))
  629.     {
  630.       *err = U_ILLEGAL_ARGUMENT_ERROR;
  631.       return;
  632.     }
  633.  
  634.   myConvType = _this->sharedData->conversionType;
  635.   /*
  636.    * Deal with stored carry over data.  This is done in the common location
  637.    * to avoid doing it for each conversion.
  638.    */
  639.   if (_this->UCharErrorBufferLength > 0)
  640.     {
  641.       int32_t myTargetIndex = 0;
  642.  
  643.       flushInternalUnicodeBuffer (_this, 
  644.                   *target,
  645.                   &myTargetIndex,
  646.                   targetLimit - *target,
  647.                   offsets?&offsets:NULL,
  648.                   err);
  649.       *target += myTargetIndex;
  650.       if (U_FAILURE (*err))
  651.     return;
  652.     }
  653.  
  654.   if (offsets) 
  655.     {
  656.       int32_t targetSize = targetLimit - *target;
  657.       int32_t i;
  658.  
  659.       switch (myConvType)
  660.     {
  661.     case UCNV_LATIN_1: case UCNV_SBCS : 
  662.       {
  663.         for (i=0; i<targetSize; i++) offsets[i] = i;
  664.         break;
  665.       }
  666.     case UCNV_UTF16_LittleEndian: case UCNV_UTF16_BigEndian: case UCNV_DBCS: 
  667.       {
  668.         for (i=0; i<targetSize; i++) 
  669.           {
  670.         offsets[i] = i*2;
  671.           }
  672.         break;
  673.       }
  674.     default:
  675.       {
  676.         
  677.         TO_UNICODE_FUNCTIONS_OFFSETS_LOGIC[(int) myConvType] (_this,
  678.                                   target,
  679.                                   targetLimit,
  680.                                   source,
  681.                                   sourceLimit,
  682.                                   offsets,
  683.                                   flush,
  684.                                   err);
  685.         return;
  686.       }
  687.     };
  688.     }
  689.   /*calls the specific conversion routines */
  690.   TO_UNICODE_FUNCTIONS[(int) myConvType] (_this,
  691.                       target,
  692.                       targetLimit,
  693.                       source,
  694.                       sourceLimit,
  695.                       offsets,
  696.                       flush,
  697.                       err);
  698.   
  699.   
  700.   return;
  701. }
  702.  
  703. int32_t   ucnv_fromUChars (const UConverter * converter,
  704.                char *target,
  705.                int32_t targetSize,
  706.                const UChar * source,
  707.                UErrorCode * err)
  708. {
  709.   const UChar *mySource = source;
  710.   const UChar *mySource_limit;
  711.   int32_t mySourceLength = 0;
  712.   UConverter myConverter;
  713.   char *myTarget = target;
  714.   char *myTarget_limit;
  715.   int32_t targetCapacity = 0;
  716.  
  717.   if (U_FAILURE (*err))
  718.     return 0;
  719.  
  720.   if ((converter == NULL) || (targetSize < 0))
  721.     {
  722.       *err = U_ILLEGAL_ARGUMENT_ERROR;
  723.       return 0;
  724.     }
  725.  
  726.   /*makes a local copy of the UConverter */
  727.   myConverter = *converter;
  728.  
  729.  
  730.   /*Removes all state info on the UConverter */
  731.   ucnv_reset (&myConverter);
  732.  
  733.   /*if the source is empty we return immediately */
  734.   mySourceLength = u_strlen (source);
  735.   if (mySourceLength == 0)
  736.     {
  737.       /*for consistency we still need to
  738.        *store 0 in the targetCapacity
  739.        *if the user requires it
  740.        */
  741.       return 0;
  742.     }
  743.  
  744.   mySource_limit = mySource + mySourceLength;
  745.   myTarget_limit = target + targetSize;
  746.  
  747.   if(myTarget_limit < target)       /*if targetsize is such that the limit*/
  748.     myTarget_limit = (char *)U_MAX_PTR;     /* would wrap around, truncate it.    */
  749.  
  750.   if (targetSize > 0)
  751.     {
  752.       ucnv_fromUnicode (&myConverter,
  753.             &myTarget,
  754.             myTarget_limit,
  755.             &mySource,
  756.             mySource_limit,
  757.             NULL,
  758.             TRUE,
  759.             err);
  760.       targetCapacity = myTarget - target;
  761.     }
  762.  
  763.   /*Updates targetCapacity to contain the number of bytes written to target */
  764.  
  765.   if (targetSize == 0)
  766.     {
  767.       *err = U_INDEX_OUTOFBOUNDS_ERROR;
  768.     }
  769.  
  770.   /* If the output buffer is exhausted, we need to stop writing
  771.    * to it but continue the conversion in order to store in targetSize
  772.    * the number of bytes that was required*/
  773.   if (*err == U_INDEX_OUTOFBOUNDS_ERROR)
  774.     {
  775.       char target2[CHUNK_SIZE];
  776.       char *target2_alias = target2;
  777.       const char *target2_limit = target2 + CHUNK_SIZE;
  778.  
  779.       /*We use a stack allocated buffer around which we loop
  780.        *(in case the output is greater than CHUNK_SIZE)
  781.        */
  782.  
  783.       while (*err == U_INDEX_OUTOFBOUNDS_ERROR)
  784.     {
  785.       *err = U_ZERO_ERROR;
  786.       target2_alias = target2;
  787.       ucnv_fromUnicode (&myConverter,
  788.                 &target2_alias,
  789.                 target2_limit,
  790.                 &mySource,
  791.                 mySource_limit,
  792.                 NULL,
  793.                 TRUE,
  794.                 err);
  795.  
  796.       /*updates the output parameter to contain the number of char required */
  797.       targetCapacity += (target2_alias - target2) + 1;
  798.     }
  799.       /*We will set the erro code to U_BUFFER_OVERFLOW_ERROR only if
  800.        *nothing graver happened in the previous loop*/
  801.       (targetCapacity)--;
  802.       if (U_SUCCESS (*err))
  803.     *err = U_BUFFER_OVERFLOW_ERROR;
  804.     }
  805.  
  806.   return targetCapacity;
  807. }
  808.  
  809. int32_t ucnv_toUChars (const UConverter * converter,
  810.                UChar * target,
  811.                int32_t targetSize,
  812.                const char *source,
  813.                int32_t sourceSize,
  814.                UErrorCode * err)
  815. {
  816.   const char *mySource = source;
  817.   const char *mySource_limit = source + sourceSize;
  818.   UConverter myConverter;
  819.   UChar *myTarget = target;
  820.   UChar *myTarget_limit;
  821.   int32_t targetCapacity;
  822.  
  823.   if (U_FAILURE (*err))
  824.     return 0;
  825.  
  826.   if ((converter == NULL) || (targetSize < 0) || (sourceSize < 0))
  827.     {
  828.       *err = U_ILLEGAL_ARGUMENT_ERROR;
  829.       return 0;
  830.     }
  831.   /*Means there is no work to be done */
  832.   if (sourceSize == 0)
  833.     {
  834.       /*for consistency we still need to
  835.        *store 0 in the targetCapacity
  836.        *if the user requires it
  837.        */
  838.       if (targetSize >= 1)
  839.     {
  840.       target[0] = 0x0000;
  841.       return 1;
  842.     }
  843.       else
  844.     return 0;
  845.     }
  846.  
  847.   /*makes a local copy of the UConverter */
  848.   myConverter = *converter;
  849.  
  850.   /*Removes all state info on the UConverter */
  851.   ucnv_reset (&myConverter);
  852.  
  853.   myTarget_limit = target + targetSize - 1;
  854.  
  855.   if(myTarget_limit < target)       /*if targetsize is such that the limit*/
  856.     myTarget_limit = ((UChar*)U_MAX_PTR) - 1; /* would wrap around, truncate it.    */
  857.  
  858.  
  859.   /*Not in pure pre-flight mode */
  860.   if (targetSize > 0)
  861.     {
  862.  
  863.       ucnv_toUnicode (&myConverter,
  864.               &myTarget,
  865.               myTarget_limit,      /*Save a spot for the Null terminator */
  866.               &mySource,
  867.               mySource_limit,
  868.               NULL,
  869.               TRUE,
  870.               err);
  871.  
  872.       /*Null terminates the string */
  873.       *(myTarget) = 0x0000;
  874.     }
  875.  
  876.  
  877.   /*Rigs targetCapacity to have at least one cell for zero termination */
  878.   /*Updates targetCapacity to contain the number of bytes written to target */
  879.   targetCapacity = 1;
  880.   targetCapacity += myTarget - target;
  881.   if (targetSize == 0)
  882.     {
  883.       *err = U_INDEX_OUTOFBOUNDS_ERROR;
  884.     }
  885.   /* If the output buffer is exhausted, we need to stop writing
  886.    * to it but if the input buffer is not exhausted,
  887.    * we need to continue the conversion in order to store in targetSize
  888.    * the number of bytes that was required
  889.    */
  890.   if (*err == U_INDEX_OUTOFBOUNDS_ERROR)
  891.     {
  892.       UChar target2[CHUNK_SIZE];
  893.       UChar *target2_alias = target2;
  894.       const UChar *target2_limit = target2 + CHUNK_SIZE;
  895.  
  896.       /*We use a stack allocated buffer around which we loop
  897.          (in case the output is greater than CHUNK_SIZE) */
  898.  
  899.       while (*err == U_INDEX_OUTOFBOUNDS_ERROR)
  900.     {
  901.       *err = U_ZERO_ERROR;
  902.       target2_alias = target2;
  903.       ucnv_toUnicode (&myConverter,
  904.               &target2_alias,
  905.               target2_limit,
  906.               &mySource,
  907.               mySource_limit,
  908.               NULL,
  909.               TRUE,
  910.               err);
  911.  
  912.       /*updates the output parameter to contain the number of char required */
  913.       targetCapacity += target2_alias - target2 + 1;
  914.     }
  915.       (targetCapacity)--;    /*adjust for last one */
  916.       if (U_SUCCESS (*err))
  917.     *err = U_BUFFER_OVERFLOW_ERROR;
  918.     }
  919.  
  920.   return targetCapacity;
  921. }
  922.  
  923. UChar ucnv_getNextUChar (UConverter * converter,
  924.              const char **source,
  925.              const char *sourceLimit,
  926.              UErrorCode * err)
  927. {
  928.   /* In case internal data had been stored
  929.    * we return the first UChar in the internal buffer,
  930.    * and update the internal state accordingly
  931.    */
  932.   if (converter->UCharErrorBufferLength > 0)
  933.     {
  934.       UChar myUChar = converter->UCharErrorBuffer[0];
  935.       /*In this memmove we update the internal buffer by
  936.        *popping the first character.
  937.          *Note that in the call itself we decrement
  938.          *UCharErrorBufferLength
  939.        */
  940.       icu_memmove (converter->UCharErrorBuffer,
  941.            converter->UCharErrorBuffer + 1,
  942.            --(converter->UCharErrorBufferLength) * sizeof (UChar));
  943.       return myUChar;
  944.     }
  945.   /*calls the specific conversion routines */
  946.   /*as dictated in a code review, avoids a switch statement */
  947.   return GET_NEXT_UChar_FUNCTIONS[(int) (converter->sharedData->conversionType)] (converter,
  948.                                           source,
  949.                                           sourceLimit,
  950.                                           err);
  951. }
  952.  
  953.  
  954.  
  955. /**************************
  956. * Will convert a sequence of bytes from one codepage to another.
  957. * @param toConverterName: The name of the converter that will be used to encode the output buffer
  958. * @param fromConverterName: The name of the converter that will be used to decode the input buffer
  959. * @param target: Pointer to the output buffer* written
  960. * @param targetLength: on input contains the capacity of target, on output the number of bytes copied to target
  961. * @param source: Pointer to the input buffer
  962. * @param sourceLength: on input contains the capacity of source, on output the number of bytes processed in "source"
  963. * @param internal: used internally to store store state data across calls
  964. * @param err: fills in an error status
  965. */
  966. void 
  967. T_UConverter_fromCodepageToCodepage (UConverter * outConverter,
  968.                      UConverter * inConverter,
  969.                      char **target,
  970.                      const char *targetLimit,
  971.                      const char **source,
  972.                      const char *sourceLimit,
  973.                      int32_t* offsets,
  974.                      bool_t flush,
  975.                      UErrorCode * err)
  976. {
  977.  
  978.   UChar out_chunk[CHUNK_SIZE];
  979.   const UChar *out_chunk_limit = out_chunk + CHUNK_SIZE;
  980.   UChar *out_chunk_alias;
  981.   UChar const *out_chunk_alias2;
  982.  
  983.  
  984.   if (U_FAILURE (*err))    return;
  985.  
  986.  
  987.   /*loops until the input buffer is completely consumed
  988.    *or if an error has be encountered
  989.    *first we convert from inConverter codepage to Unicode
  990.    *then from Unicode to outConverter codepage
  991.    */
  992.   while ((*source != sourceLimit) && U_SUCCESS (*err))
  993.     {
  994.       out_chunk_alias = out_chunk;
  995.       ucnv_toUnicode (inConverter,
  996.               &out_chunk_alias,
  997.               out_chunk_limit,
  998.               source,
  999.               sourceLimit,
  1000.               NULL,
  1001.               flush,
  1002.               err);
  1003.  
  1004.       /*U_INDEX_OUTOFBOUNDS_ERROR means that the output "CHUNK" is full
  1005.        *we will require at least another loop (it's a recoverable error)
  1006.        */
  1007.  
  1008.       if (U_SUCCESS (*err) || (*err == U_INDEX_OUTOFBOUNDS_ERROR))
  1009.     {
  1010.       *err = U_ZERO_ERROR;
  1011.       out_chunk_alias2 = out_chunk;
  1012.  
  1013.       while ((out_chunk_alias2 != out_chunk_alias) && U_SUCCESS (*err))
  1014.         {
  1015.           ucnv_fromUnicode (outConverter,
  1016.                 target,
  1017.                 targetLimit,
  1018.                 &out_chunk_alias2,
  1019.                 out_chunk_alias,
  1020.                 NULL,
  1021.                 TRUE,
  1022.                 err);
  1023.  
  1024.         }
  1025.     }
  1026.       else
  1027.     break;
  1028.     }
  1029.  
  1030.   return;
  1031. }
  1032.  
  1033. int32_t  ucnv_convert(const char *toConverterName,
  1034.               const char *fromConverterName,
  1035.               char *target,
  1036.               int32_t targetSize,
  1037.               const char *source,
  1038.               int32_t sourceSize,
  1039.               UErrorCode * err)
  1040. {
  1041.   const char *mySource = source;
  1042.   const char *mySource_limit = source + sourceSize;
  1043.   int32_t mySourceLength = 0;
  1044.   UConverter *inConverter;
  1045.   UConverter *outConverter;
  1046.   char *myTarget = target;
  1047.   int32_t targetCapacity = 0;
  1048.  
  1049.   if (U_FAILURE (*err))
  1050.     return 0;
  1051.  
  1052.   if ((targetSize < 0) || (sourceSize < 0))
  1053.     {
  1054.       *err = U_ILLEGAL_ARGUMENT_ERROR;
  1055.       return 0;
  1056.     }
  1057.  
  1058.   /*if there is no input data, we're done */
  1059.   if (sourceSize == 0)
  1060.     {
  1061.       /*in case the caller passed an output ptr
  1062.        *we update it
  1063.        */
  1064.       return 0;
  1065.     }
  1066.  
  1067.   /*create the converters */
  1068.   inConverter = ucnv_open (fromConverterName, err);
  1069.   if (U_FAILURE (*err)) return 0;
  1070.   outConverter = ucnv_open (toConverterName, err);
  1071.   if (U_FAILURE (*err))
  1072.     {
  1073.       ucnv_close (inConverter);
  1074.       return 0;
  1075.     }
  1076.  
  1077.  
  1078.   if (targetSize > 0)
  1079.     {
  1080.       T_UConverter_fromCodepageToCodepage (outConverter,
  1081.                        inConverter,
  1082.                        &myTarget,
  1083.                        target + targetSize,
  1084.                        &mySource,
  1085.                        mySource_limit,
  1086.                        NULL,
  1087.                        TRUE,
  1088.                        err);
  1089.     }
  1090.  
  1091.  
  1092.   /*Updates targetCapacity to contain the number of bytes written to target */
  1093.   targetCapacity = myTarget - target;
  1094.   if (targetSize == 0)
  1095.     {
  1096.       *err = U_INDEX_OUTOFBOUNDS_ERROR;
  1097.     }
  1098.  
  1099.   /* If the output buffer is exhausted, we need to stop writing
  1100.    * to it but continue the conversion in order to store in targetSize
  1101.    * the number of bytes that was required*/
  1102.   if (*err == U_INDEX_OUTOFBOUNDS_ERROR)
  1103.     {
  1104.       char target2[CHUNK_SIZE];
  1105.       char *target2_alias = target2;
  1106.       const char *target2_limit = target2 + CHUNK_SIZE;
  1107.  
  1108.       /*We use a stack allocated buffer around which we loop
  1109.        *(in case the output is greater than CHUNK_SIZE)
  1110.        */
  1111.  
  1112.       while (*err == U_INDEX_OUTOFBOUNDS_ERROR)
  1113.     {
  1114.       *err = U_ZERO_ERROR;
  1115.       target2_alias = target2;
  1116.       T_UConverter_fromCodepageToCodepage (outConverter,
  1117.                            inConverter,
  1118.                            &target2_alias,
  1119.                            target2_limit,
  1120.                            &mySource,
  1121.                            mySource_limit,
  1122.                            NULL,
  1123.                            TRUE,
  1124.                            err);
  1125.  
  1126.       /*updates the output parameter to contain the number of char required */
  1127.       targetCapacity += (target2_alias - target2) + 1;
  1128.     }
  1129.       /*We will set the erro code to U_BUFFER_OVERFLOW_ERROR only if
  1130.        *nothing graver happened in the previous loop*/
  1131.       (targetCapacity)--;
  1132.       if (U_SUCCESS (*err))
  1133.     *err = U_BUFFER_OVERFLOW_ERROR;
  1134.     }
  1135.  
  1136.   ucnv_close (inConverter);
  1137.   ucnv_close (outConverter);
  1138.  
  1139.   return targetCapacity;
  1140. }
  1141.  
  1142. UConverterType ucnv_getType(const UConverter* converter)
  1143. {
  1144.   return converter->sharedData->conversionType;
  1145. }
  1146.  
  1147. void ucnv_getStarters(const UConverter* converter, 
  1148.               bool_t starters[256],
  1149.               UErrorCode* err)
  1150. {
  1151.   if (U_FAILURE(*err)) return;
  1152.   /*Fire off an error if converter is not UCNV_MBCS*/
  1153.   if (converter->sharedData->conversionType != UCNV_MBCS) 
  1154.     {
  1155.       *err = U_ILLEGAL_ARGUMENT_ERROR;
  1156.       return;
  1157.     }
  1158.   
  1159.   /*fill's in the starters boolean array*/
  1160.   icu_memcpy(starters, converter->sharedData->table->mbcs.starters, 256*sizeof(bool_t));
  1161.   return;
  1162. }
  1163.