2 * MultiByteToWideChar implementation
4 * Copyright 2000 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wine/unicode.h"
26 /* get the decomposition of a Unicode char */
27 static int get_decomposition( WCHAR src
, WCHAR
*dst
, unsigned int dstlen
)
29 extern const WCHAR unicode_decompose_table
[];
30 const WCHAR
*ptr
= unicode_decompose_table
;
34 ptr
= unicode_decompose_table
+ ptr
[src
>> 8];
35 ptr
= unicode_decompose_table
+ ptr
[(src
>> 4) & 0x0f] + 2 * (src
& 0x0f);
37 if (dstlen
<= 1) return 0;
38 /* apply the decomposition recursively to the first char */
39 if ((res
= get_decomposition( *ptr
, dst
, dstlen
-1 ))) dst
[res
++] = ptr
[1];
43 /* check src string for invalid chars; return non-zero if invalid char found */
44 static inline int check_invalid_chars_sbcs( const struct sbcs_table
*table
,
45 const unsigned char *src
, unsigned int srclen
)
47 const WCHAR
* const cp2uni
= table
->cp2uni
;
50 if (cp2uni
[*src
] == table
->info
.def_unicode_char
&& *src
!= table
->info
.def_char
)
58 /* mbstowcs for single-byte code page */
59 /* all lengths are in characters, not bytes */
60 static inline int mbstowcs_sbcs( const struct sbcs_table
*table
,
61 const unsigned char *src
, unsigned int srclen
,
62 WCHAR
*dst
, unsigned int dstlen
)
64 const WCHAR
* const cp2uni
= table
->cp2uni
;
69 /* buffer too small: fill it up to dstlen and return error */
79 case 16: dst
[15] = cp2uni
[src
[15]];
80 case 15: dst
[14] = cp2uni
[src
[14]];
81 case 14: dst
[13] = cp2uni
[src
[13]];
82 case 13: dst
[12] = cp2uni
[src
[12]];
83 case 12: dst
[11] = cp2uni
[src
[11]];
84 case 11: dst
[10] = cp2uni
[src
[10]];
85 case 10: dst
[9] = cp2uni
[src
[9]];
86 case 9: dst
[8] = cp2uni
[src
[8]];
87 case 8: dst
[7] = cp2uni
[src
[7]];
88 case 7: dst
[6] = cp2uni
[src
[6]];
89 case 6: dst
[5] = cp2uni
[src
[5]];
90 case 5: dst
[4] = cp2uni
[src
[4]];
91 case 4: dst
[3] = cp2uni
[src
[3]];
92 case 3: dst
[2] = cp2uni
[src
[2]];
93 case 2: dst
[1] = cp2uni
[src
[1]];
94 case 1: dst
[0] = cp2uni
[src
[0]];
97 if (srclen
< 16) return ret
;
104 /* mbstowcs for single-byte code page with char decomposition */
105 static int mbstowcs_sbcs_decompose( const struct sbcs_table
*table
,
106 const unsigned char *src
, unsigned int srclen
,
107 WCHAR
*dst
, unsigned int dstlen
)
109 const WCHAR
* const cp2uni
= table
->cp2uni
;
112 if (!dstlen
) /* compute length */
114 WCHAR dummy
[4]; /* no decomposition is larger than 4 chars */
115 for (len
= 0; srclen
; srclen
--, src
++)
116 len
+= get_decomposition( cp2uni
[*src
], dummy
, 4 );
120 for (len
= dstlen
; srclen
&& len
; srclen
--, src
++)
122 int res
= get_decomposition( cp2uni
[*src
], dst
, len
);
127 if (srclen
) return -1; /* overflow */
131 /* query necessary dst length for src string */
132 static inline int get_length_dbcs( const struct dbcs_table
*table
,
133 const unsigned char *src
, unsigned int srclen
)
135 const unsigned char * const cp2uni_lb
= table
->cp2uni_leadbytes
;
138 for (len
= 0; srclen
; srclen
--, src
++, len
++)
142 if (!--srclen
) break; /* partial char, ignore it */
149 /* check src string for invalid chars; return non-zero if invalid char found */
150 static inline int check_invalid_chars_dbcs( const struct dbcs_table
*table
,
151 const unsigned char *src
, unsigned int srclen
)
153 const WCHAR
* const cp2uni
= table
->cp2uni
;
154 const unsigned char * const cp2uni_lb
= table
->cp2uni_leadbytes
;
158 unsigned char off
= cp2uni_lb
[*src
];
159 if (off
) /* multi-byte char */
161 if (srclen
== 1) break; /* partial char, error */
162 if (cp2uni
[(off
<< 8) + src
[1]] == table
->info
.def_unicode_char
&&
163 ((src
[0] << 8) | src
[1]) != table
->info
.def_char
) break;
167 else if (cp2uni
[*src
] == table
->info
.def_unicode_char
&&
168 *src
!= table
->info
.def_char
) break;
175 /* mbstowcs for double-byte code page */
176 /* all lengths are in characters, not bytes */
177 static inline int mbstowcs_dbcs( const struct dbcs_table
*table
,
178 const unsigned char *src
, unsigned int srclen
,
179 WCHAR
*dst
, unsigned int dstlen
)
181 const WCHAR
* const cp2uni
= table
->cp2uni
;
182 const unsigned char * const cp2uni_lb
= table
->cp2uni_leadbytes
;
185 if (!dstlen
) return get_length_dbcs( table
, src
, srclen
);
187 for (len
= dstlen
; srclen
&& len
; len
--, srclen
--, src
++, dst
++)
189 unsigned char off
= cp2uni_lb
[*src
];
192 if (!--srclen
) break; /* partial char, ignore it */
194 *dst
= cp2uni
[(off
<< 8) + *src
];
196 else *dst
= cp2uni
[*src
];
198 if (srclen
) return -1; /* overflow */
203 /* mbstowcs for double-byte code page with character decomposition */
204 static int mbstowcs_dbcs_decompose( const struct dbcs_table
*table
,
205 const unsigned char *src
, unsigned int srclen
,
206 WCHAR
*dst
, unsigned int dstlen
)
208 const WCHAR
* const cp2uni
= table
->cp2uni
;
209 const unsigned char * const cp2uni_lb
= table
->cp2uni_leadbytes
;
214 if (!dstlen
) /* compute length */
216 WCHAR dummy
[4]; /* no decomposition is larger than 4 chars */
217 for (len
= 0; srclen
; srclen
--, src
++)
219 unsigned char off
= cp2uni_lb
[*src
];
222 if (!--srclen
) break; /* partial char, ignore it */
224 ch
= cp2uni
[(off
<< 8) + *src
];
226 else ch
= cp2uni
[*src
];
227 len
+= get_decomposition( ch
, dummy
, 4 );
232 for (len
= dstlen
; srclen
&& len
; srclen
--, src
++)
234 unsigned char off
= cp2uni_lb
[*src
];
237 if (!--srclen
) break; /* partial char, ignore it */
239 ch
= cp2uni
[(off
<< 8) + *src
];
241 else ch
= cp2uni
[*src
];
242 if (!(res
= get_decomposition( ch
, dst
, len
))) break;
246 if (srclen
) return -1; /* overflow */
251 /* return -1 on dst buffer overflow, -2 on invalid input char */
252 int cp_mbstowcs( const union cptable
*table
, int flags
,
253 const char *src
, int srclen
,
254 WCHAR
*dst
, int dstlen
)
256 if (table
->info
.char_size
== 1)
258 if (flags
& MB_ERR_INVALID_CHARS
)
260 if (check_invalid_chars_sbcs( &table
->sbcs
, src
, srclen
)) return -2;
262 if (!(flags
& MB_COMPOSITE
))
264 if (!dstlen
) return srclen
;
265 return mbstowcs_sbcs( &table
->sbcs
, src
, srclen
, dst
, dstlen
);
267 return mbstowcs_sbcs_decompose( &table
->sbcs
, src
, srclen
, dst
, dstlen
);
271 if (flags
& MB_ERR_INVALID_CHARS
)
273 if (check_invalid_chars_dbcs( &table
->dbcs
, src
, srclen
)) return -2;
275 if (!(flags
& MB_COMPOSITE
))
276 return mbstowcs_dbcs( &table
->dbcs
, src
, srclen
, dst
, dstlen
);
278 return mbstowcs_dbcs_decompose( &table
->dbcs
, src
, srclen
, dst
, dstlen
);