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