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