OLD | NEW |
(Empty) | |
| 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 */ |
| 20 |
| 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" |
| 27 |
| 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 |
| 34 |
| 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 } |
| 49 |
| 50 UBool |
| 51 ufmt_isdigit(UChar c, |
| 52 int32_t radix) |
| 53 { |
| 54 int digitVal = ufmt_digitvalue(c); |
| 55 |
| 56 return (UBool)(digitVal < radix && digitVal >= 0); |
| 57 } |
| 58 |
| 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) |
| 61 |
| 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; |
| 73 |
| 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); |
| 80 |
| 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 } |
| 86 |
| 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 } |
| 95 |
| 96 *len = length; |
| 97 } |
| 98 |
| 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; |
| 108 |
| 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 } |
| 127 |
| 128 *len = length; |
| 129 } |
| 130 |
| 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; |
| 139 |
| 140 |
| 141 /* intialize parameters */ |
| 142 limit = buffer + *len; |
| 143 count = 0; |
| 144 result = 0; |
| 145 |
| 146 /* iterate through buffer */ |
| 147 while(ufmt_isdigit(*buffer, radix) && buffer < limit) { |
| 148 |
| 149 /* read the next digit */ |
| 150 result *= radix; |
| 151 result += ufmt_digitvalue(*buffer++); |
| 152 |
| 153 /* increment our count */ |
| 154 ++count; |
| 155 } |
| 156 |
| 157 *len = count; |
| 158 return result; |
| 159 } |
| 160 |
| 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; |
| 172 |
| 173 /* intialize variables */ |
| 174 count = 0; |
| 175 offset = 0; |
| 176 result.ptr = NULL; |
| 177 |
| 178 /* Skip the leading zeros */ |
| 179 while(buffer[count] == DIGIT_0 || u_isspace(buffer[count])) { |
| 180 count++; |
| 181 offset++; |
| 182 } |
| 183 |
| 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 } |
| 189 |
| 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 } |
| 194 |
| 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]); |
| 208 |
| 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 } |
| 217 |
| 218 return result.ptr; |
| 219 } |
| 220 |
| 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); |
| 228 |
| 229 if(U_FAILURE(status) || defConverter == 0) |
| 230 return 0; |
| 231 |
| 232 if(sSize <= 0) { |
| 233 sSize = uprv_strlen(s) + 1; |
| 234 } |
| 235 |
| 236 /* perform the conversion in one swoop */ |
| 237 if(target != 0) { |
| 238 |
| 239 alias = target; |
| 240 ucnv_toUnicode(defConverter, &alias, alias + tSize, &s, s + sSize - 1, |
| 241 NULL, TRUE, &status); |
| 242 |
| 243 |
| 244 /* add the null terminator */ |
| 245 *alias = 0x0000; |
| 246 } |
| 247 |
| 248 u_releaseDefaultConverter(defConverter); |
| 249 |
| 250 return target; |
| 251 } |
| 252 |
| 253 |
OLD | NEW |