intl/icu/source/io/ufmt_cmn.c

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /*
     2 ******************************************************************************
     3 *
     4 *   Copyright (C) 1998-2006, International Business Machines
     5 *   Corporation and others.  All Rights Reserved.
     6 *
     7 ******************************************************************************
     8 *
     9 * File ufmt_cmn.c
    10 *
    11 * Modification History:
    12 *
    13 *   Date        Name        Description
    14 *   12/02/98    stephen     Creation.
    15 *   03/12/99    stephen     Modified for new C API.
    16 *   03/15/99    stephen     Added defaultCPToUnicode, unicodeToDefaultCP
    17 *   07/19/99    stephen     Fixed bug in defaultCPToUnicode
    18 ******************************************************************************
    19 */
    21 #include "cstring.h"
    22 #include "cmemory.h"
    23 #include "ufmt_cmn.h"
    24 #include "unicode/uchar.h"
    25 #include "unicode/ucnv.h"
    26 #include "ustr_cnv.h"
    28 #define DIGIT_0     0x0030
    29 #define DIGIT_9     0x0039
    30 #define LOWERCASE_A 0x0061
    31 #define UPPERCASE_A 0x0041
    32 #define LOWERCASE_Z 0x007A
    33 #define UPPERCASE_Z 0x005A
    35 int
    36 ufmt_digitvalue(UChar c)
    37 {
    38     if( ((c>=DIGIT_0)&&(c<=DIGIT_9)) ||
    39         ((c>=LOWERCASE_A)&&(c<=LOWERCASE_Z)) ||
    40         ((c>=UPPERCASE_A)&&(c<=UPPERCASE_Z))  )
    41     {
    42       return c - DIGIT_0 - (c >= 0x0041 ? (c >= 0x0061 ? 39 : 7) : 0);
    43     }
    44     else
    45     {
    46       return -1;
    47     }
    48 }
    50 UBool
    51 ufmt_isdigit(UChar     c,
    52              int32_t     radix)
    53 {
    54     int digitVal = ufmt_digitvalue(c);
    56     return (UBool)(digitVal < radix && digitVal >= 0);
    57 }
    59 #define TO_UC_DIGIT(a) a <= 9 ? (DIGIT_0 + a) : (0x0037 + a)
    60 #define TO_LC_DIGIT(a) a <= 9 ? (DIGIT_0 + a) : (0x0057 + a)
    62 void 
    63 ufmt_64tou(UChar     *buffer, 
    64           int32_t   *len,
    65           uint64_t  value, 
    66           uint8_t  radix,
    67           UBool     uselower,
    68           int32_t   minDigits)
    69 {
    70     int32_t  length = 0;
    71     uint32_t digit;
    72     UChar    *left, *right, temp;
    74     do {
    75         digit = (uint32_t)(value % radix);
    76         value = value / radix;
    77         buffer[length++] = (UChar)(uselower ? TO_LC_DIGIT(digit) 
    78             : TO_UC_DIGIT(digit));
    79     } while(value);
    81     /* pad with zeroes to make it minDigits long */
    82     if(minDigits != -1 && length < minDigits) {
    83         while(length < minDigits && length < *len)
    84             buffer[length++] = DIGIT_0;  /*zero padding */
    85     }
    87     /* reverse the buffer */
    88     left     = buffer;
    89     right = buffer + length;
    90     while(left < --right) {
    91         temp     = *left;
    92         *left++     = *right;
    93         *right     = temp;
    94     }
    96     *len = length;
    97 }
    99 void 
   100 ufmt_ptou(UChar    *buffer, 
   101           int32_t   *len,
   102           void      *value, 
   103           UBool     uselower)
   104 {
   105     int32_t i;
   106     int32_t length = 0;
   107     uint8_t *ptrIdx = (uint8_t *)&value;
   109 #if U_IS_BIG_ENDIAN
   110     for (i = 0; i < (int32_t)sizeof(void *); i++)
   111 #else
   112     for (i = (int32_t)sizeof(void *)-1; i >= 0 ; i--)
   113 #endif
   114     {
   115         uint8_t byteVal = ptrIdx[i];
   116         uint16_t firstNibble = (uint16_t)(byteVal>>4);
   117         uint16_t secondNibble = (uint16_t)(byteVal&0xF);
   118         if (uselower) {
   119             buffer[length++]=TO_LC_DIGIT(firstNibble);
   120             buffer[length++]=TO_LC_DIGIT(secondNibble);
   121         }
   122         else {
   123             buffer[length++]=TO_UC_DIGIT(firstNibble);
   124             buffer[length++]=TO_UC_DIGIT(secondNibble);
   125         }
   126     }
   128     *len = length;
   129 }
   131 int64_t
   132 ufmt_uto64(const UChar     *buffer, 
   133           int32_t     *len,
   134           int8_t     radix)
   135 {
   136     const UChar     *limit;
   137     int32_t         count;
   138     int64_t        result;
   141     /* intialize parameters */
   142     limit     = buffer + *len;
   143     count     = 0;
   144     result    = 0;
   146     /* iterate through buffer */
   147     while(ufmt_isdigit(*buffer, radix) && buffer < limit) {
   149         /* read the next digit */
   150         result *= radix;
   151         result += ufmt_digitvalue(*buffer++);
   153         /* increment our count */
   154         ++count;
   155     }
   157     *len = count;
   158     return result;
   159 }
   161 #define NIBBLE_PER_BYTE 2
   162 void *
   163 ufmt_utop(const UChar     *buffer,
   164           int32_t     *len)
   165 {
   166     int32_t count, resultIdx, incVal, offset;
   167     /* This union allows the pointer to be written as an array. */
   168     union {
   169         void *ptr;
   170         uint8_t bytes[sizeof(void*)];
   171     } result;
   173     /* intialize variables */
   174     count      = 0;
   175     offset     = 0;
   176     result.ptr = NULL;
   178     /* Skip the leading zeros */
   179     while(buffer[count] == DIGIT_0 || u_isspace(buffer[count])) {
   180         count++;
   181         offset++;
   182     }
   184     /* iterate through buffer, stop when you hit the end */
   185     while(ufmt_isdigit(buffer[count], 16) && count < *len) {
   186         /* increment the count consumed */
   187         ++count;
   188     }
   190     /* detect overflow */
   191     if (count - offset > (int32_t)(sizeof(void*)*NIBBLE_PER_BYTE)) {
   192         offset = count - (int32_t)(sizeof(void*)*NIBBLE_PER_BYTE);
   193     }
   195     /* Initialize the direction of the input */
   196 #if U_IS_BIG_ENDIAN
   197     incVal = -1;
   198     resultIdx = (int32_t)(sizeof(void*) - 1);
   199 #else
   200     incVal = 1;
   201     resultIdx = 0;
   202 #endif
   203     /* Write how much was consumed. */
   204     *len = count;
   205     while(--count >= offset) {
   206         /* Get the first nibble of the byte */
   207         uint8_t byte = (uint8_t)ufmt_digitvalue(buffer[count]);
   209         if (count > offset) {
   210             /* Get the second nibble of the byte when available */
   211             byte = (uint8_t)(byte + (ufmt_digitvalue(buffer[--count]) << 4));
   212         }
   213         /* Write the byte into the array */
   214         result.bytes[resultIdx] = byte;
   215         resultIdx += incVal;
   216     }
   218     return result.ptr;
   219 }
   221 UChar*
   222 ufmt_defaultCPToUnicode(const char *s, int32_t sSize,
   223                         UChar *target, int32_t tSize)
   224 {
   225     UChar *alias;
   226     UErrorCode status = U_ZERO_ERROR;
   227     UConverter *defConverter = u_getDefaultConverter(&status);
   229     if(U_FAILURE(status) || defConverter == 0)
   230         return 0;
   232     if(sSize <= 0) {
   233         sSize = uprv_strlen(s) + 1;
   234     }
   236     /* perform the conversion in one swoop */
   237     if(target != 0) {
   239         alias = target;
   240         ucnv_toUnicode(defConverter, &alias, alias + tSize, &s, s + sSize - 1, 
   241             NULL, TRUE, &status);
   244         /* add the null terminator */
   245         *alias = 0x0000;
   246     }
   248     u_releaseDefaultConverter(defConverter);
   250     return target;
   251 }

mercurial