IDirectDraw,IDirectDraw2,IDirectDraw4 fixed up in regard to COM usage.
[wine] / unicode / mbtowc.c
1 /*
2  * MultiByteToWideChar implementation
3  *
4  * Copyright 2000 Alexandre Julliard
5  */
6
7 #include <string.h>
8
9 #include "winnls.h"
10 #include "wine/unicode.h"
11
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 )
15 {
16     const WCHAR * const cp2uni = table->cp2uni;
17     while (srclen)
18     {
19         if (cp2uni[*src] == table->info.def_unicode_char && *src != table->info.def_char)
20             break;
21         src++;
22         srclen--;
23     }
24     return srclen;
25 }
26
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 )
32 {
33     const WCHAR * const cp2uni = table->cp2uni;
34     int ret = srclen;
35
36     if (dstlen < srclen)
37     {
38         /* buffer too small: fill it up to dstlen and return error */
39         srclen = dstlen;
40         ret = -1;
41     }
42
43     for (;;)
44     {
45         switch(srclen)
46         {
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;
65         }
66         if (srclen < 16) return ret;
67         dst += 16;
68         src += 16;
69         srclen -= 16;
70     }
71 }
72
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 )
76 {
77     const unsigned char * const cp2uni_lb = table->cp2uni_leadbytes;
78     int len;
79
80     for (len = 0; srclen; srclen--, src++, len++)
81     {
82         if (cp2uni_lb[*src])
83         {
84             if (!--srclen) break;  /* partial char, ignore it */
85             src++;
86         }
87     }
88     return len;
89 }
90
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 )
94 {
95     const WCHAR * const cp2uni = table->cp2uni;
96     const unsigned char * const cp2uni_lb = table->cp2uni_leadbytes;
97
98     while (srclen)
99     {
100         unsigned char off = cp2uni_lb[*src];
101         if (off)  /* multi-byte char */
102         {
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--;
108         }
109         else if (cp2uni[*src] == table->info.def_unicode_char &&
110                  *src != table->info.def_char) break;
111         src++;
112         srclen--;
113     }
114     return srclen;
115 }
116
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 )
122 {
123     const WCHAR * const cp2uni = table->cp2uni;
124     const unsigned char * const cp2uni_lb = table->cp2uni_leadbytes;
125     int len;
126
127     for (len = dstlen; srclen && len; len--, srclen--, src++, dst++)
128     {
129         unsigned char off = cp2uni_lb[*src];
130         if (off)
131         {
132             if (!--srclen) break;  /* partial char, ignore it */
133             src++;
134             *dst = cp2uni[(off << 8) + *src];
135         }
136         else *dst = cp2uni[*src];
137     }
138     if (srclen) return -1;  /* overflow */
139     return dstlen - len;
140 }
141
142
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 )
147 {
148     if (table->info.char_size == 1)
149     {
150         if (flags & MB_ERR_INVALID_CHARS)
151         {
152             if (check_invalid_chars_sbcs( &table->sbcs, src, srclen )) return -2;
153         }
154         if (!dstlen) return srclen;
155         return mbstowcs_sbcs( &table->sbcs, src, srclen, dst, dstlen );
156     }
157     else /* mbcs */
158     {
159         if (flags & MB_ERR_INVALID_CHARS)
160         {
161             if (check_invalid_chars_dbcs( &table->dbcs, src, srclen )) return -2;
162         }
163         if (!dstlen) return get_length_dbcs( &table->dbcs, src, srclen );
164         return mbstowcs_dbcs( &table->dbcs, src, srclen, dst, dstlen );
165     }
166 }