2 * MultiByteToWideChar implementation
4 * Copyright 2000 Alexandre Julliard
10 #include "wine/unicode.h"
12 /* check src string for invalid chars; return non-zero if invalid char found */
13 static inline int check_invalid_chars_sbcs( const struct sbcs_table
*table
,
14 const unsigned char *src
, unsigned int srclen
)
16 const WCHAR
* const cp2uni
= table
->cp2uni
;
19 if (cp2uni
[*src
] == table
->info
.def_unicode_char
&& *src
!= table
->info
.def_char
)
27 /* mbstowcs for single-byte code page */
28 /* all lengths are in characters, not bytes */
29 static inline int mbstowcs_sbcs( const struct sbcs_table
*table
,
30 const unsigned char *src
, unsigned int srclen
,
31 WCHAR
*dst
, unsigned int dstlen
)
33 const WCHAR
* const cp2uni
= table
->cp2uni
;
38 /* buffer too small: fill it up to dstlen and return error */
48 case 16: dst
[15] = cp2uni
[src
[15]];
49 case 15: dst
[14] = cp2uni
[src
[14]];
50 case 14: dst
[13] = cp2uni
[src
[13]];
51 case 13: dst
[12] = cp2uni
[src
[12]];
52 case 12: dst
[11] = cp2uni
[src
[11]];
53 case 11: dst
[10] = cp2uni
[src
[10]];
54 case 10: dst
[9] = cp2uni
[src
[9]];
55 case 9: dst
[8] = cp2uni
[src
[8]];
56 case 8: dst
[7] = cp2uni
[src
[7]];
57 case 7: dst
[6] = cp2uni
[src
[6]];
58 case 6: dst
[5] = cp2uni
[src
[5]];
59 case 5: dst
[4] = cp2uni
[src
[4]];
60 case 4: dst
[3] = cp2uni
[src
[3]];
61 case 3: dst
[2] = cp2uni
[src
[2]];
62 case 2: dst
[1] = cp2uni
[src
[1]];
63 case 1: dst
[0] = cp2uni
[src
[0]];
66 if (srclen
< 16) return ret
;
73 /* query necessary dst length for src string */
74 static inline int get_length_dbcs( const struct dbcs_table
*table
,
75 const unsigned char *src
, unsigned int srclen
)
77 const unsigned char * const cp2uni_lb
= table
->cp2uni_leadbytes
;
80 for (len
= 0; srclen
; srclen
--, src
++, len
++)
84 if (!--srclen
) break; /* partial char, ignore it */
91 /* check src string for invalid chars; return non-zero if invalid char found */
92 static inline int check_invalid_chars_dbcs( const struct dbcs_table
*table
,
93 const unsigned char *src
, unsigned int srclen
)
95 const WCHAR
* const cp2uni
= table
->cp2uni
;
96 const unsigned char * const cp2uni_lb
= table
->cp2uni_leadbytes
;
100 unsigned char off
= cp2uni_lb
[*src
];
101 if (off
) /* multi-byte char */
103 if (srclen
== 1) break; /* partial char, error */
104 if (cp2uni
[(off
<< 8) + src
[1]] == table
->info
.def_unicode_char
&&
105 ((src
[0] << 8) | src
[1]) != table
->info
.def_char
) break;
109 else if (cp2uni
[*src
] == table
->info
.def_unicode_char
&&
110 *src
!= table
->info
.def_char
) break;
117 /* mbstowcs for double-byte code page */
118 /* all lengths are in characters, not bytes */
119 static inline int mbstowcs_dbcs( const struct dbcs_table
*table
,
120 const unsigned char *src
, unsigned int srclen
,
121 WCHAR
*dst
, unsigned int dstlen
)
123 const WCHAR
* const cp2uni
= table
->cp2uni
;
124 const unsigned char * const cp2uni_lb
= table
->cp2uni_leadbytes
;
127 for (len
= dstlen
; srclen
&& len
; len
--, srclen
--, src
++, dst
++)
129 unsigned char off
= cp2uni_lb
[*src
];
132 if (!--srclen
) break; /* partial char, ignore it */
134 *dst
= cp2uni
[(off
<< 8) + *src
];
136 else *dst
= cp2uni
[*src
];
138 if (srclen
) return -1; /* overflow */
143 /* return -1 on dst buffer overflow, -2 on invalid input char */
144 int cp_mbstowcs( const union cptable
*table
, int flags
,
145 const char *src
, int srclen
,
146 WCHAR
*dst
, int dstlen
)
148 if (table
->info
.char_size
== 1)
150 if (flags
& MB_ERR_INVALID_CHARS
)
152 if (check_invalid_chars_sbcs( &table
->sbcs
, src
, srclen
)) return -2;
154 if (!dstlen
) return srclen
;
155 return mbstowcs_sbcs( &table
->sbcs
, src
, srclen
, dst
, dstlen
);
159 if (flags
& MB_ERR_INVALID_CHARS
)
161 if (check_invalid_chars_dbcs( &table
->dbcs
, src
, srclen
)) return -2;
163 if (!dstlen
) return get_length_dbcs( &table
->dbcs
, src
, srclen
);
164 return mbstowcs_dbcs( &table
->dbcs
, src
, srclen
, dst
, dstlen
);