]> git.saurik.com Git - apple/icu.git/blob - icuSources/io/ufmt_cmn.c
ICU-6.2.8.tar.gz
[apple/icu.git] / icuSources / io / ufmt_cmn.c
1 /*
2 ******************************************************************************
3 *
4 * Copyright (C) 1998-2004, 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 - 0x0030 - (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 ? (0x0030 + a) : (0x0037 + a)
60 #define TO_LC_DIGIT(a) a <= 9 ? (0x0030 + 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++] = 0x0030; /*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 void *
162 ufmt_utop(const UChar *buffer,
163 int32_t *len)
164 {
165 /*
166 TODO: Fix this code so that it will work with pointers that are 2<=sizeof(void*)<=16
167 */
168 const UChar *limit;
169 int32_t count;
170 int64_t result;
171
172
173 /* intialize parameters */
174 limit = buffer + *len;
175 count = 0;
176 result = 0;
177
178 /* iterate through buffer */
179 /* limit to sixteen iterations since that is the max that an int64_t can contain for pointer work */
180 while(ufmt_isdigit(*buffer, 16) && buffer < limit) {
181
182 /* read the next digit */
183 result *= 16;
184 result += ufmt_digitvalue(*buffer++);
185
186 /* increment our count */
187 ++count;
188 }
189
190 *len = count;
191 return (void *)result;
192 }
193
194 UChar*
195 ufmt_defaultCPToUnicode(const char *s, int32_t sSize,
196 UChar *target, int32_t tSize)
197 {
198 UChar *alias;
199 UErrorCode status = U_ZERO_ERROR;
200 UConverter *defConverter = u_getDefaultConverter(&status);
201
202 if(U_FAILURE(status) || defConverter == 0)
203 return 0;
204
205 if(sSize <= 0) {
206 sSize = uprv_strlen(s) + 1;
207 }
208
209 /* perform the conversion in one swoop */
210 if(target != 0) {
211
212 alias = target;
213 ucnv_toUnicode(defConverter, &alias, alias + tSize, &s, s + sSize - 1,
214 NULL, TRUE, &status);
215
216
217 /* add the null terminator */
218 *alias = 0x0000;
219 }
220
221 u_releaseDefaultConverter(defConverter);
222
223 return target;
224 }
225
226