Implemented DosFileHandleToWin32Handle, Win32HandleToDosFileHandle and
[wine/multimedia.git] / unicode / mbtowc.c
blob77d62c4bc77b1dda83e9942995cf6f68b2671085
1 /*
2 * MultiByteToWideChar implementation
4 * Copyright 2000 Alexandre Julliard
5 */
7 #include <string.h>
9 #include "winnls.h"
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;
17 while (srclen)
19 if (cp2uni[*src] == table->info.def_unicode_char && *src != table->info.def_char)
20 break;
21 src++;
22 srclen--;
24 return srclen;
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;
34 int ret = srclen;
36 if (dstlen < srclen)
38 /* buffer too small: fill it up to dstlen and return error */
39 srclen = dstlen;
40 ret = -1;
43 for (;;)
45 switch(srclen)
47 default:
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]];
64 case 0: break;
66 if (srclen < 16) return ret;
67 dst += 16;
68 src += 16;
69 srclen -= 16;
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;
78 int len;
80 for (len = 0; srclen; srclen--, src++, len++)
82 if (cp2uni_lb[*src])
84 if (!--srclen) break; /* partial char, ignore it */
85 src++;
88 return len;
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;
98 while (srclen)
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;
106 src++;
107 srclen--;
109 else if (cp2uni[*src] == table->info.def_unicode_char &&
110 *src != table->info.def_char) break;
111 src++;
112 srclen--;
114 return srclen;
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;
125 int len;
127 for (len = dstlen; srclen && len; len--, srclen--, src++, dst++)
129 unsigned char off = cp2uni_lb[*src];
130 if (off)
132 if (!--srclen) break; /* partial char, ignore it */
133 src++;
134 *dst = cp2uni[(off << 8) + *src];
136 else *dst = cp2uni[*src];
138 if (srclen) return -1; /* overflow */
139 return dstlen - len;
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 );
157 else /* mbcs */
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 );