|
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 |