1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/io/ufmt_cmn.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,253 @@ 1.4 +/* 1.5 +****************************************************************************** 1.6 +* 1.7 +* Copyright (C) 1998-2006, International Business Machines 1.8 +* Corporation and others. All Rights Reserved. 1.9 +* 1.10 +****************************************************************************** 1.11 +* 1.12 +* File ufmt_cmn.c 1.13 +* 1.14 +* Modification History: 1.15 +* 1.16 +* Date Name Description 1.17 +* 12/02/98 stephen Creation. 1.18 +* 03/12/99 stephen Modified for new C API. 1.19 +* 03/15/99 stephen Added defaultCPToUnicode, unicodeToDefaultCP 1.20 +* 07/19/99 stephen Fixed bug in defaultCPToUnicode 1.21 +****************************************************************************** 1.22 +*/ 1.23 + 1.24 +#include "cstring.h" 1.25 +#include "cmemory.h" 1.26 +#include "ufmt_cmn.h" 1.27 +#include "unicode/uchar.h" 1.28 +#include "unicode/ucnv.h" 1.29 +#include "ustr_cnv.h" 1.30 + 1.31 +#define DIGIT_0 0x0030 1.32 +#define DIGIT_9 0x0039 1.33 +#define LOWERCASE_A 0x0061 1.34 +#define UPPERCASE_A 0x0041 1.35 +#define LOWERCASE_Z 0x007A 1.36 +#define UPPERCASE_Z 0x005A 1.37 + 1.38 +int 1.39 +ufmt_digitvalue(UChar c) 1.40 +{ 1.41 + if( ((c>=DIGIT_0)&&(c<=DIGIT_9)) || 1.42 + ((c>=LOWERCASE_A)&&(c<=LOWERCASE_Z)) || 1.43 + ((c>=UPPERCASE_A)&&(c<=UPPERCASE_Z)) ) 1.44 + { 1.45 + return c - DIGIT_0 - (c >= 0x0041 ? (c >= 0x0061 ? 39 : 7) : 0); 1.46 + } 1.47 + else 1.48 + { 1.49 + return -1; 1.50 + } 1.51 +} 1.52 + 1.53 +UBool 1.54 +ufmt_isdigit(UChar c, 1.55 + int32_t radix) 1.56 +{ 1.57 + int digitVal = ufmt_digitvalue(c); 1.58 + 1.59 + return (UBool)(digitVal < radix && digitVal >= 0); 1.60 +} 1.61 + 1.62 +#define TO_UC_DIGIT(a) a <= 9 ? (DIGIT_0 + a) : (0x0037 + a) 1.63 +#define TO_LC_DIGIT(a) a <= 9 ? (DIGIT_0 + a) : (0x0057 + a) 1.64 + 1.65 +void 1.66 +ufmt_64tou(UChar *buffer, 1.67 + int32_t *len, 1.68 + uint64_t value, 1.69 + uint8_t radix, 1.70 + UBool uselower, 1.71 + int32_t minDigits) 1.72 +{ 1.73 + int32_t length = 0; 1.74 + uint32_t digit; 1.75 + UChar *left, *right, temp; 1.76 + 1.77 + do { 1.78 + digit = (uint32_t)(value % radix); 1.79 + value = value / radix; 1.80 + buffer[length++] = (UChar)(uselower ? TO_LC_DIGIT(digit) 1.81 + : TO_UC_DIGIT(digit)); 1.82 + } while(value); 1.83 + 1.84 + /* pad with zeroes to make it minDigits long */ 1.85 + if(minDigits != -1 && length < minDigits) { 1.86 + while(length < minDigits && length < *len) 1.87 + buffer[length++] = DIGIT_0; /*zero padding */ 1.88 + } 1.89 + 1.90 + /* reverse the buffer */ 1.91 + left = buffer; 1.92 + right = buffer + length; 1.93 + while(left < --right) { 1.94 + temp = *left; 1.95 + *left++ = *right; 1.96 + *right = temp; 1.97 + } 1.98 + 1.99 + *len = length; 1.100 +} 1.101 + 1.102 +void 1.103 +ufmt_ptou(UChar *buffer, 1.104 + int32_t *len, 1.105 + void *value, 1.106 + UBool uselower) 1.107 +{ 1.108 + int32_t i; 1.109 + int32_t length = 0; 1.110 + uint8_t *ptrIdx = (uint8_t *)&value; 1.111 + 1.112 +#if U_IS_BIG_ENDIAN 1.113 + for (i = 0; i < (int32_t)sizeof(void *); i++) 1.114 +#else 1.115 + for (i = (int32_t)sizeof(void *)-1; i >= 0 ; i--) 1.116 +#endif 1.117 + { 1.118 + uint8_t byteVal = ptrIdx[i]; 1.119 + uint16_t firstNibble = (uint16_t)(byteVal>>4); 1.120 + uint16_t secondNibble = (uint16_t)(byteVal&0xF); 1.121 + if (uselower) { 1.122 + buffer[length++]=TO_LC_DIGIT(firstNibble); 1.123 + buffer[length++]=TO_LC_DIGIT(secondNibble); 1.124 + } 1.125 + else { 1.126 + buffer[length++]=TO_UC_DIGIT(firstNibble); 1.127 + buffer[length++]=TO_UC_DIGIT(secondNibble); 1.128 + } 1.129 + } 1.130 + 1.131 + *len = length; 1.132 +} 1.133 + 1.134 +int64_t 1.135 +ufmt_uto64(const UChar *buffer, 1.136 + int32_t *len, 1.137 + int8_t radix) 1.138 +{ 1.139 + const UChar *limit; 1.140 + int32_t count; 1.141 + int64_t result; 1.142 + 1.143 + 1.144 + /* intialize parameters */ 1.145 + limit = buffer + *len; 1.146 + count = 0; 1.147 + result = 0; 1.148 + 1.149 + /* iterate through buffer */ 1.150 + while(ufmt_isdigit(*buffer, radix) && buffer < limit) { 1.151 + 1.152 + /* read the next digit */ 1.153 + result *= radix; 1.154 + result += ufmt_digitvalue(*buffer++); 1.155 + 1.156 + /* increment our count */ 1.157 + ++count; 1.158 + } 1.159 + 1.160 + *len = count; 1.161 + return result; 1.162 +} 1.163 + 1.164 +#define NIBBLE_PER_BYTE 2 1.165 +void * 1.166 +ufmt_utop(const UChar *buffer, 1.167 + int32_t *len) 1.168 +{ 1.169 + int32_t count, resultIdx, incVal, offset; 1.170 + /* This union allows the pointer to be written as an array. */ 1.171 + union { 1.172 + void *ptr; 1.173 + uint8_t bytes[sizeof(void*)]; 1.174 + } result; 1.175 + 1.176 + /* intialize variables */ 1.177 + count = 0; 1.178 + offset = 0; 1.179 + result.ptr = NULL; 1.180 + 1.181 + /* Skip the leading zeros */ 1.182 + while(buffer[count] == DIGIT_0 || u_isspace(buffer[count])) { 1.183 + count++; 1.184 + offset++; 1.185 + } 1.186 + 1.187 + /* iterate through buffer, stop when you hit the end */ 1.188 + while(ufmt_isdigit(buffer[count], 16) && count < *len) { 1.189 + /* increment the count consumed */ 1.190 + ++count; 1.191 + } 1.192 + 1.193 + /* detect overflow */ 1.194 + if (count - offset > (int32_t)(sizeof(void*)*NIBBLE_PER_BYTE)) { 1.195 + offset = count - (int32_t)(sizeof(void*)*NIBBLE_PER_BYTE); 1.196 + } 1.197 + 1.198 + /* Initialize the direction of the input */ 1.199 +#if U_IS_BIG_ENDIAN 1.200 + incVal = -1; 1.201 + resultIdx = (int32_t)(sizeof(void*) - 1); 1.202 +#else 1.203 + incVal = 1; 1.204 + resultIdx = 0; 1.205 +#endif 1.206 + /* Write how much was consumed. */ 1.207 + *len = count; 1.208 + while(--count >= offset) { 1.209 + /* Get the first nibble of the byte */ 1.210 + uint8_t byte = (uint8_t)ufmt_digitvalue(buffer[count]); 1.211 + 1.212 + if (count > offset) { 1.213 + /* Get the second nibble of the byte when available */ 1.214 + byte = (uint8_t)(byte + (ufmt_digitvalue(buffer[--count]) << 4)); 1.215 + } 1.216 + /* Write the byte into the array */ 1.217 + result.bytes[resultIdx] = byte; 1.218 + resultIdx += incVal; 1.219 + } 1.220 + 1.221 + return result.ptr; 1.222 +} 1.223 + 1.224 +UChar* 1.225 +ufmt_defaultCPToUnicode(const char *s, int32_t sSize, 1.226 + UChar *target, int32_t tSize) 1.227 +{ 1.228 + UChar *alias; 1.229 + UErrorCode status = U_ZERO_ERROR; 1.230 + UConverter *defConverter = u_getDefaultConverter(&status); 1.231 + 1.232 + if(U_FAILURE(status) || defConverter == 0) 1.233 + return 0; 1.234 + 1.235 + if(sSize <= 0) { 1.236 + sSize = uprv_strlen(s) + 1; 1.237 + } 1.238 + 1.239 + /* perform the conversion in one swoop */ 1.240 + if(target != 0) { 1.241 + 1.242 + alias = target; 1.243 + ucnv_toUnicode(defConverter, &alias, alias + tSize, &s, s + sSize - 1, 1.244 + NULL, TRUE, &status); 1.245 + 1.246 + 1.247 + /* add the null terminator */ 1.248 + *alias = 0x0000; 1.249 + } 1.250 + 1.251 + u_releaseDefaultConverter(defConverter); 1.252 + 1.253 + return target; 1.254 +} 1.255 + 1.256 +