• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
ufmt_digitvalue(UChar c)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
ufmt_isdigit(UChar c,int32_t radix)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
ufmt_64tou(UChar * buffer,int32_t * len,uint64_t value,uint8_t radix,UBool uselower,int32_t minDigits)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
ufmt_ptou(UChar * buffer,int32_t * len,void * value,UBool uselower)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
ufmt_uto64(const UChar * buffer,int32_t * len,int8_t radix)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 *
ufmt_utop(const UChar * buffer,int32_t * len)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*
ufmt_defaultCPToUnicode(const char * s,int32_t sSize,UChar * target,int32_t tSize)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 
254