home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / common / ucnv_err.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-19  |  11.8 KB  |  436 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.  *
  14.  *  ucnv_err.c
  15.  *  Implements error behaviour functions called by T_UConverter_{from,to}Unicode
  16.  *
  17.  */
  18.  
  19. #include "uhash.h"
  20. #include "ucmp8.h"
  21. #include "ucmp16.h"
  22. #include "ucnv_bld.h"
  23. #include "ucnv_err.h"
  24. #include "ucnv_cnv.h"
  25. #include "cmemory.h"
  26. #include "ucnv.h"
  27.  
  28. #define VALUE_STRING_LENGTH 32
  29. /*Magic # 32 = 4(number of char in value string) * 8(max number of bytes per char for any converter) */
  30. #define CODEPOINT_STRING_LENGTH 7
  31. #define UNICODE_PERCENT_SIGN_CODEPOINT 0x0025
  32. #define UNICODE_U_CODEPOINT 0x0055
  33. #define UNICODE_X_CODEPOINT 0x0058
  34.  
  35.  
  36. #define ToOffset(a) a<=9?(0x0030+a):(0x0030+a+7)
  37.  
  38. bool_t 
  39.   CONVERSION_U_SUCCESS (UErrorCode err)
  40. {
  41.   if ((err == U_INVALID_CHAR_FOUND) || (err == U_ILLEGAL_CHAR_FOUND))    return FALSE;
  42.   else    return TRUE;
  43. }
  44.  
  45. /*Takes a int32_t and fills in  a UChar* string with that number "radix"-based
  46.  * and padded with "pad" zeroes
  47.  */
  48. static void   itou (UChar * buffer, int32_t i, int32_t radix, int32_t pad)
  49. {
  50.   int32_t length = 0;
  51.   int32_t num = 0;
  52.   int8_t digit;
  53.   int32_t j;
  54.   UChar temp;
  55.  
  56.   while (i > radix)
  57.     {
  58.       num = i / radix;
  59.       digit = (int8_t) (i - num * radix);
  60.       buffer[length++] = (UChar) (ToOffset (digit));
  61.       i = num;
  62.     }
  63.  
  64.   buffer[length] = (UChar) (ToOffset (i));
  65.  
  66.   while (length < pad)   buffer[++length] = (UChar) 0x0030;    /*zero padding */
  67.   buffer[length--] = (UChar) 0x0000;
  68.   
  69.   /*Reverses the string */
  70.   for (j = 0; j < (pad / 2); j++)
  71.     {
  72.       temp = buffer[length - j];
  73.       buffer[length - j] = buffer[j];
  74.       buffer[j] = temp;
  75.     }
  76.  
  77.   return;
  78. }
  79.  
  80. /*Function Pointer STOPS at the ILLEGAL_SEQUENCE */
  81. void   UCNV_FROM_U_CALLBACK_STOP (UConverter * _this,
  82.                   char **target,
  83.                   const char *targetLimit,
  84.                   const UChar ** source,
  85.                   const UChar * sourceLimit,
  86.                   int32_t *offsets,
  87.                   bool_t flush,
  88.                   UErrorCode * err)
  89. {
  90.   return;
  91. }
  92.  
  93.  
  94. /*Function Pointer STOPS at the ILLEGAL_SEQUENCE */
  95. void   UCNV_TO_U_CALLBACK_STOP (UConverter * _this,
  96.                    UChar ** target,
  97.                    const UChar * targetLimit,
  98.                    const char **source,
  99.                    const char *sourceLimit,
  100.                    int32_t *offsets,
  101.                    bool_t flush,
  102.                    UErrorCode * err)
  103. {
  104.   return;
  105. }
  106.  
  107. void   UCNV_FROM_U_CALLBACK_SKIP (UConverter * _this,
  108.                   char **target,
  109.                   const char *targetLimit,
  110.                   const UChar ** source,
  111.                   const UChar * sourceLimit,
  112.                   int32_t *offsets,
  113.                   bool_t flush,
  114.                   UErrorCode * err)
  115. {
  116.   if (CONVERSION_U_SUCCESS (*err))    return;
  117.   *err = U_ZERO_ERROR;
  118. }
  119.  
  120. void   UCNV_FROM_U_CALLBACK_SUBSTITUTE (UConverter * _this,
  121.                     char **target,
  122.                     const char *targetLimit,
  123.                     const UChar ** source,
  124.                     const UChar * sourceLimit,
  125.                     int32_t *offsets,
  126.                     bool_t flush,
  127.                     UErrorCode * err)
  128. {
  129.   char togo[5];
  130.   int32_t togoLen;
  131.  
  132.  
  133.  
  134.   if (CONVERSION_U_SUCCESS (*err)) return;
  135.   
  136.   /*In case we're dealing with a modal converter a la UCNV_EBCDIC_STATEFUL,
  137.     we need to make sure that the emitting of the substitution charater in the right mode*/
  138.   icu_memcpy(togo, _this->subChar, togoLen = _this->subCharLen);
  139.   if (ucnv_getType(_this) == UCNV_EBCDIC_STATEFUL)
  140.     {
  141.       if ((_this->fromUnicodeStatus)&&(togoLen != 2))
  142.     {
  143.       togo[0] = UCNV_SI;
  144.       togo[1] = _this->subChar[0];
  145.       togo[2] = UCNV_SO;
  146.       togoLen = 3;
  147.     }
  148.       else if (!(_this->fromUnicodeStatus)&&(togoLen != 1))
  149.     {
  150.       togo[0] = UCNV_SO;
  151.       togo[1] = _this->subChar[0];
  152.       togo[2] = _this->subChar[1];
  153.       togo[3] = UCNV_SI;
  154.       togoLen = 4;
  155.     }
  156.     }
  157.   
  158.   /*if we have enough space on the output buffer we just copy
  159.     the subchar there and update the pointer */  
  160.   if ((targetLimit - *target) >= togoLen)
  161.     {
  162.       icu_memcpy (*target, togo, togoLen);
  163.       *target += togoLen;
  164.       *err = U_ZERO_ERROR;
  165.       if (offsets)
  166.     {
  167.       int i=0;
  168.       for (i=0;i<togoLen;i++) offsets[i]=0;
  169.       offsets += togoLen;
  170.     }
  171.     }
  172.   else
  173.     {
  174.       /*if we don't have enough space on the output buffer
  175.        *we copy as much as we can to it, update that pointer.
  176.        *copy the rest in the internal buffer, and increase the
  177.        *length marker
  178.        */
  179.       icu_memcpy (*target, togo, (targetLimit - *target));
  180.       if (offsets)
  181.     {
  182.       int i=0;
  183.       for (i=0;i<(targetLimit - *target);i++) offsets[i]=0;
  184.       offsets += (targetLimit - *target);
  185.     }
  186.       icu_memcpy (_this->charErrorBuffer + _this->charErrorBufferLength,
  187.           togo + (targetLimit - *target),
  188.           togoLen - (targetLimit - *target));
  189.       _this->charErrorBufferLength += togoLen - (targetLimit - *target);
  190.       *target += (targetLimit - *target);
  191.       *err = U_INDEX_OUTOFBOUNDS_ERROR;
  192.     }
  193.  
  194.   return;
  195.  
  196. }
  197.  
  198. /*uses itou to get a unicode escape sequence of the offensive sequence,
  199.  *uses a clean copy (resetted) of the converter, to convert that unicode
  200.  *escape sequence to the target codepage (if conversion failure happens then
  201.  *we revert to substituting with subchar)
  202.  */
  203. void   UCNV_FROM_U_CALLBACK_ESCAPE (UConverter * _this,
  204.                          char **target,
  205.                          const char *targetLimit,
  206.                          const UChar ** source,
  207.                          const UChar * sourceLimit,
  208.                          int32_t *offsets,
  209.                          bool_t flush,
  210.                          UErrorCode * err)
  211. {
  212.  
  213.   UChar valueString[VALUE_STRING_LENGTH];
  214.   int32_t valueStringLength = 0;
  215.   const UChar *mySource = *source;
  216.   UChar codepoint[CODEPOINT_STRING_LENGTH];
  217.   int32_t i = 0;
  218.   /*Makes a bitwise copy of the converter passwd in */
  219.   UConverter myConverter = *_this;
  220.   char myTarget[VALUE_STRING_LENGTH];
  221.   char *myTargetAlias = myTarget;
  222.   const UChar *myValueSource = NULL;
  223.   UErrorCode err2 = U_ZERO_ERROR;
  224.   uint32_t myFromUnicodeStatus = _this->fromUnicodeStatus;
  225.  
  226.  
  227.   if (CONVERSION_U_SUCCESS (*err))   return;
  228.  
  229.   ucnv_reset (&myConverter);
  230.   myConverter.fromUnicodeStatus = myFromUnicodeStatus;
  231.   
  232.   ucnv_setFromUCallBack (&myConverter,
  233.              (UConverterFromUCallback) UCNV_FROM_U_CALLBACK_STOP,
  234.              &err2);
  235.   if (U_FAILURE (err2))
  236.     {
  237.       *err = err2;
  238.       return;
  239.     }
  240.  
  241.   codepoint[0] = (UChar) UNICODE_PERCENT_SIGN_CODEPOINT;    /* adding % */
  242.   codepoint[1] = (UChar) UNICODE_U_CODEPOINT;    /* adding U */
  243.  
  244.   while (i < _this->invalidUCharLength)
  245.     {
  246.       itou (codepoint + 2, _this->invalidUCharBuffer[i++], 16, 4);
  247.       icu_memcpy (valueString + valueStringLength, codepoint, sizeof (UChar) * 6);
  248.       valueStringLength += CODEPOINT_STRING_LENGTH - 1;
  249.     }
  250.  
  251.   myValueSource = valueString;
  252.  
  253.   /*converts unicode escape sequence */
  254.   ucnv_fromUnicode (&myConverter,
  255.             &myTargetAlias,
  256.             myTargetAlias + VALUE_STRING_LENGTH,
  257.             &myValueSource,
  258.             myValueSource + CODEPOINT_STRING_LENGTH - 1,
  259.             NULL,
  260.             TRUE,
  261.             &err2);
  262.   
  263.   if (U_FAILURE (err2))
  264.     {
  265.       UCNV_FROM_U_CALLBACK_SUBSTITUTE (_this,
  266.                        target,
  267.                        targetLimit,
  268.                        source,
  269.                        sourceLimit,
  270.                        offsets,
  271.                        flush,
  272.                        err);
  273.       return;
  274.     }
  275.  
  276.  
  277.   
  278.   valueStringLength = myTargetAlias - myTarget;
  279.   
  280.   /*if we have enough space on the output buffer we just copy
  281.    * the subchar there and update the pointer
  282.    */
  283.   if ((targetLimit - *target) >= valueStringLength)
  284.     {
  285.       icu_memcpy (*target, myTarget, valueStringLength);
  286.       *target += valueStringLength;
  287.       *err = U_ZERO_ERROR;
  288.  
  289.       if (offsets)
  290.     {
  291.       int i=0;
  292.       for (i=0;i<valueStringLength;i++) offsets[i]=0;
  293.       offsets += valueStringLength;
  294.     }
  295.     }
  296.   else
  297.     {
  298.       /*if we don't have enough space on the output buffer
  299.        *we copy as much as we can to it, update that pointer.
  300.        *copy the rest in the internal buffer, and increase the
  301.        *length marker
  302.        */
  303.  
  304.       if (offsets)
  305.     {
  306.       int i=0;
  307.       for (i=0;i<(targetLimit - *target);i++) offsets[i]=0;
  308.       offsets += (targetLimit - *target);
  309.     }
  310.       icu_memcpy (*target, myTarget, (targetLimit - *target));
  311.       icu_memcpy (_this->charErrorBuffer + _this->charErrorBufferLength,
  312.           myTarget + (targetLimit - *target),
  313.           valueStringLength - (targetLimit - *target));
  314.       _this->charErrorBufferLength += valueStringLength - (targetLimit - *target);
  315.       *target += (targetLimit - *target);
  316.       *err = U_INDEX_OUTOFBOUNDS_ERROR;
  317.     }
  318.  
  319.   return;
  320. }
  321.  
  322.  
  323.  
  324. void UCNV_TO_U_CALLBACK_SKIP (UConverter * _this,
  325.                  UChar ** target,
  326.                  const UChar * targetLimit,
  327.                  const char **source,
  328.                  const char *sourceLimit,
  329.                  int32_t *offsets,
  330.                  bool_t flush,
  331.                  UErrorCode * err)
  332. {
  333.   if (CONVERSION_U_SUCCESS (*err))   return;
  334.   *err = U_ZERO_ERROR;
  335. }
  336.  
  337. void   UCNV_TO_U_CALLBACK_SUBSTITUTE (UConverter * _this,
  338.                      UChar ** target,
  339.                      const UChar * targetLimit,
  340.                      const char **source,
  341.                      const char *sourceLimit,
  342.                      int32_t *offsets,
  343.                      bool_t flush,
  344.                      UErrorCode * err)
  345. {
  346.   
  347.   if (CONVERSION_U_SUCCESS (*err))   return;
  348.   
  349.   if ((targetLimit - *target) >= 1)
  350.     {
  351.       **target = 0xFFFD;
  352.       (*target)++;
  353.       if (offsets)  *offsets = 0;
  354.       *err = U_ZERO_ERROR;
  355.     }
  356.   else
  357.     {
  358.       _this->UCharErrorBuffer[_this->UCharErrorBufferLength] = 0xFFFD;
  359.       _this->UCharErrorBufferLength++;
  360.       *err = U_INDEX_OUTOFBOUNDS_ERROR;
  361.     }
  362.   
  363.   return;
  364.   
  365. }
  366.  
  367. /*uses itou to get a unicode escape sequence of the offensive sequence,
  368.  *and uses that as the substitution sequence
  369.  */
  370. void  UCNV_TO_U_CALLBACK_ESCAPE (UConverter * _this,
  371.                          UChar ** target,
  372.                          const UChar * targetLimit,
  373.                          const char **source,
  374.                          const char *sourceLimit,
  375.                          int32_t *offsets,
  376.                          bool_t flush,
  377.                          UErrorCode * err)
  378. {
  379.   UChar uniValueString[VALUE_STRING_LENGTH];
  380.   int32_t valueStringLength = 0;
  381.   const unsigned char *mySource = (const unsigned char *) *source;
  382.   UChar codepoint[CODEPOINT_STRING_LENGTH];
  383.   int32_t j = 0, i = 0;
  384.   const int32_t* offsets_end = offsets +( targetLimit - *target);
  385.   
  386.   if (CONVERSION_U_SUCCESS (*err))   return;
  387.   
  388.   codepoint[0] = (UChar) UNICODE_PERCENT_SIGN_CODEPOINT;    /* adding % */
  389.   codepoint[1] = (UChar) UNICODE_X_CODEPOINT;    /* adding X */
  390.   
  391.   while (i < _this->invalidCharLength)
  392.     {
  393.       itou (codepoint + 2, _this->invalidCharBuffer[i++], 16, 2);
  394.       icu_memcpy (uniValueString + valueStringLength, codepoint, sizeof (UChar) * 4);
  395.       valueStringLength += 4;
  396.     }
  397.   
  398.   if ((targetLimit - *target) >= valueStringLength)
  399.     {
  400.       /*if we have enough space on the output buffer we just copy
  401.        * the subchar there and update the pointer
  402.        */
  403.       icu_memcpy (*target, uniValueString, (sizeof (UChar)) * (valueStringLength));
  404.       if (offsets) 
  405.     {
  406.       for (i = 0; i < valueStringLength; i++)  offsets[i] = 0;
  407.     }
  408.       *target += valueStringLength;
  409.       
  410.       *err = U_ZERO_ERROR;
  411.     }
  412.   else
  413.     {
  414.       /*if we don't have enough space on the output buffer
  415.        *we copy as much as we can to it, update that pointer.
  416.        *copy the rest in the internal buffer, and increase the
  417.        *length marker
  418.        */
  419.       icu_memcpy (*target, uniValueString, (sizeof (UChar)) * (targetLimit - *target));
  420.       if (offsets) 
  421.     {
  422.       for (i = 0; i < (targetLimit - *target); i++)  offsets[i] = 0;
  423.     }        
  424.       
  425.       
  426.       icu_memcpy (_this->UCharErrorBuffer,
  427.           uniValueString + (targetLimit - *target),
  428.           (sizeof (UChar)) * (valueStringLength - (targetLimit - *target)));
  429.       _this->UCharErrorBufferLength += valueStringLength - (targetLimit - *target);
  430.       *target += (targetLimit - *target);
  431.       *err = U_INDEX_OUTOFBOUNDS_ERROR;
  432.     }
  433.   
  434.   return;
  435. }
  436.