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
23 #include "wine/unicode.h"
25 typedef unsigned char uchar
;
27 /* get the decomposition of a Unicode char */
28 int get_decomposition( WCHAR src
, WCHAR
*dst
, unsigned int dstlen
)
30 extern const WCHAR unicode_decompose_table
[];
31 const WCHAR
*ptr
= unicode_decompose_table
;
35 ptr
= unicode_decompose_table
+ ptr
[src
>> 8];
36 ptr
= unicode_decompose_table
+ ptr
[(src
>> 4) & 0x0f] + 2 * (src
& 0x0f);
38 if (dstlen
<= 1) return 0;
39 /* apply the decomposition recursively to the first char */
40 if ((res
= get_decomposition( *ptr
, dst
, dstlen
-1 ))) dst
[res
++] = ptr
[1];
44 /* check src string for invalid chars; return non-zero if invalid char found */
45 static inline int check_invalid_chars_sbcs( const struct sbcs_table
*table
,
46 const unsigned char *src
, unsigned int srclen
)
48 const WCHAR
* const cp2uni
= table
->cp2uni
;
51 if (cp2uni
[*src
] == table
->info
.def_unicode_char
&& *src
!= table
->info
.def_char
)
59 /* mbstowcs for single-byte code page */
60 /* all lengths are in characters, not bytes */
61 static inline int mbstowcs_sbcs( const struct sbcs_table
*table
,
62 const unsigned char *src
, unsigned int srclen
,
63 WCHAR
*dst
, unsigned int dstlen
)
65 const WCHAR
* const cp2uni
= table
->cp2uni
;
70 /* buffer too small: fill it up to dstlen and return error */
80 case 16: dst
[15] = cp2uni
[src
[15]];
81 case 15: dst
[14] = cp2uni
[src
[14]];
82 case 14: dst
[13] = cp2uni
[src
[13]];
83 case 13: dst
[12] = cp2uni
[src
[12]];
84 case 12: dst
[11] = cp2uni
[src
[11]];
85 case 11: dst
[10] = cp2uni
[src
[10]];
86 case 10: dst
[9] = cp2uni
[src
[9]];
87 case 9: dst
[8] = cp2uni
[src
[8]];
88 case 8: dst
[7] = cp2uni
[src
[7]];
89 case 7: dst
[6] = cp2uni
[src
[6]];
90 case 6: dst
[5] = cp2uni
[src
[5]];
91 case 5: dst
[4] = cp2uni
[src
[4]];
92 case 4: dst
[3] = cp2uni
[src
[3]];
93 case 3: dst
[2] = cp2uni
[src
[2]];
94 case 2: dst
[1] = cp2uni
[src
[1]];
95 case 1: dst
[0] = cp2uni
[src
[0]];
98 if (srclen
< 16) return ret
;
105 /* mbstowcs for single-byte code page with char decomposition */
106 static int mbstowcs_sbcs_decompose( const struct sbcs_table
*table
,
107 const unsigned char *src
, unsigned int srclen
,
108 WCHAR
*dst
, unsigned int dstlen
)
110 const WCHAR
* const cp2uni
= table
->cp2uni
;
113 if (!dstlen
) /* compute length */
115 WCHAR dummy
[4]; /* no decomposition is larger than 4 chars */
116 for (len
= 0; srclen
; srclen
--, src
++)
117 len
+= get_decomposition( cp2uni
[*src
], dummy
, 4 );
121 for (len
= dstlen
; srclen
&& len
; srclen
--, src
++)
123 int res
= get_decomposition( cp2uni
[*src
], dst
, len
);
128 if (srclen
) return -1; /* overflow */
132 /* query necessary dst length for src string */
133 static inline int get_length_dbcs( const struct dbcs_table
*table
,
134 const unsigned char *src
, unsigned int srclen
)
136 const unsigned char * const cp2uni_lb
= table
->cp2uni_leadbytes
;
139 for (len
= 0; srclen
; srclen
--, src
++, len
++)
143 if (!--srclen
) break; /* partial char, ignore it */
150 /* check src string for invalid chars; return non-zero if invalid char found */
151 static inline int check_invalid_chars_dbcs( const struct dbcs_table
*table
,
152 const unsigned char *src
, unsigned int srclen
)
154 const WCHAR
* const cp2uni
= table
->cp2uni
;
155 const unsigned char * const cp2uni_lb
= table
->cp2uni_leadbytes
;
159 unsigned char off
= cp2uni_lb
[*src
];
160 if (off
) /* multi-byte char */
162 if (srclen
== 1) break; /* partial char, error */
163 if (cp2uni
[(off
<< 8) + src
[1]] == table
->info
.def_unicode_char
&&
164 ((src
[0] << 8) | src
[1]) != table
->info
.def_char
) break;
168 else if (cp2uni
[*src
] == table
->info
.def_unicode_char
&&
169 *src
!= table
->info
.def_char
) break;
176 /* mbstowcs for double-byte code page */
177 /* all lengths are in characters, not bytes */
178 static inline int mbstowcs_dbcs( const struct dbcs_table
*table
,
179 const unsigned char *src
, unsigned int srclen
,
180 WCHAR
*dst
, unsigned int dstlen
)
182 const WCHAR
* const cp2uni
= table
->cp2uni
;
183 const unsigned char * const cp2uni_lb
= table
->cp2uni_leadbytes
;
186 if (!dstlen
) return get_length_dbcs( table
, src
, srclen
);
188 for (len
= dstlen
; srclen
&& len
; len
--, srclen
--, src
++, dst
++)
190 unsigned char off
= cp2uni_lb
[*src
];
193 if (!--srclen
) break; /* partial char, ignore it */
195 *dst
= cp2uni
[(off
<< 8) + *src
];
197 else *dst
= cp2uni
[*src
];
199 if (srclen
) return -1; /* overflow */
204 /* mbstowcs for double-byte code page with character decomposition */
205 static int mbstowcs_dbcs_decompose( const struct dbcs_table
*table
,
206 const unsigned char *src
, unsigned int srclen
,
207 WCHAR
*dst
, unsigned int dstlen
)
209 const WCHAR
* const cp2uni
= table
->cp2uni
;
210 const unsigned char * const cp2uni_lb
= table
->cp2uni_leadbytes
;
215 if (!dstlen
) /* compute length */
217 WCHAR dummy
[4]; /* no decomposition is larger than 4 chars */
218 for (len
= 0; srclen
; srclen
--, src
++)
220 unsigned char off
= cp2uni_lb
[*src
];
223 if (!--srclen
) break; /* partial char, ignore it */
225 ch
= cp2uni
[(off
<< 8) + *src
];
227 else ch
= cp2uni
[*src
];
228 len
+= get_decomposition( ch
, dummy
, 4 );
233 for (len
= dstlen
; srclen
&& len
; srclen
--, src
++)
235 unsigned char off
= cp2uni_lb
[*src
];
238 if (!--srclen
) break; /* partial char, ignore it */
240 ch
= cp2uni
[(off
<< 8) + *src
];
242 else ch
= cp2uni
[*src
];
243 if (!(res
= get_decomposition( ch
, dst
, len
))) break;
247 if (srclen
) return -1; /* overflow */
252 /* return -1 on dst buffer overflow, -2 on invalid input char */
253 int wine_cp_mbstowcs( const union cptable
*table
, int flags
,
254 const char *src
, int srclen
,
255 WCHAR
*dst
, int dstlen
)
257 if (table
->info
.char_size
== 1)
259 if (flags
& MB_ERR_INVALID_CHARS
)
261 if (check_invalid_chars_sbcs( &table
->sbcs
, (const uchar
*)src
, srclen
)) return -2;
263 if (!(flags
& MB_COMPOSITE
))
265 if (!dstlen
) return srclen
;
266 return mbstowcs_sbcs( &table
->sbcs
, (const uchar
*)src
, srclen
, dst
, dstlen
);
268 return mbstowcs_sbcs_decompose( &table
->sbcs
, (const uchar
*)src
, srclen
, dst
, dstlen
);
272 if (flags
& MB_ERR_INVALID_CHARS
)
274 if (check_invalid_chars_dbcs( &table
->dbcs
, (const uchar
*)src
, srclen
)) return -2;
276 if (!(flags
& MB_COMPOSITE
))
277 return mbstowcs_dbcs( &table
->dbcs
, (const uchar
*)src
, srclen
, dst
, dstlen
);
279 return mbstowcs_dbcs_decompose( &table
->dbcs
, (const uchar
*)src
, srclen
, dst
, dstlen
);
283 /* CP_SYMBOL implementation */
284 /* return -1 on dst buffer overflow */
285 int wine_cpsymbol_mbstowcs( const char *src
, int srclen
, WCHAR
*dst
, int dstlen
)
288 if( dstlen
== 0) return srclen
;
289 len
= dstlen
> srclen
? srclen
: dstlen
;
290 for( i
= 0; i
< len
; i
++)
292 unsigned char c
= src
[ i
];
298 if( srclen
> len
) return -1;