intl/icu/source/io/ufmt_cmn.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial