Enable utf8 I/O stuff when compiling with MinGW.
[platform/upstream/flac.git] / src / share / win_utf8_io / win_utf8_io.c
1
2 #include <stdio.h>
3 #include <sys/stat.h>
4 #include <sys/utime.h>
5 #include <io.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <stdarg.h>
9 #include <windows.h> /* for WideCharToMultiByte and MultiByteToWideChar */
10
11 #include "share/win_utf8_io.h"
12
13 /* convert WCHAR stored Unicode string to UTF-8. Caller is responsible for freeing memory */
14 static
15 char *utf8_from_wchar(const wchar_t *wstr)
16 {
17         char *utf8str;
18         int len;
19
20         if (!wstr) return NULL;
21         if ((len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL)) == 0) return NULL;
22         if ((utf8str = (char *)malloc(++len)) == NULL) return NULL;
23         if (WideCharToMultiByte(CP_UTF8, 0, wstr, -1, utf8str, len, NULL, NULL) == 0) {
24                 free(utf8str);
25                 utf8str = NULL;
26         }
27
28         return utf8str;
29 }
30
31 /* convert UTF-8 back to WCHAR. Caller is responsible for freeing memory */
32 static
33 wchar_t *wchar_from_utf8(const char *str)
34 {
35         wchar_t *widestr;
36         int len;
37
38         if (!str) return NULL;
39         len=(int)strlen(str)+1;
40         if ((widestr = (wchar_t *)malloc(len*sizeof(wchar_t))) != NULL) {
41                 if (MultiByteToWideChar(CP_UTF8, 0, str, len, widestr, len) == 0) {
42                         if (MultiByteToWideChar(CP_ACP, 0, str, len, widestr, len) == 0) { /* try conversion from Ansi in case the initial UTF-8 conversion had failed */
43                                 free(widestr);
44                                 widestr = NULL;
45                         }
46                 }
47         }
48
49         return widestr;
50 }
51
52 /* retrieve WCHAR commandline, expand wildcards and convert everything to UTF-8 */
53 int get_utf8_argv(int *argc, char ***argv)
54 {
55         typedef int (__cdecl *__wgetmainargs_)(int*, wchar_t***, wchar_t***, int, int*);
56         __wgetmainargs_ __wgetmainargs;
57         HMODULE handle;
58         int wargc;
59         wchar_t **wargv;
60         wchar_t **wenv;
61         char **utf8argv;
62         int ret, i;
63
64         if ((handle = LoadLibrary("msvcrt.dll")) == NULL) return 1;
65         if ((__wgetmainargs = (__wgetmainargs_)GetProcAddress(handle, "__wgetmainargs")) == NULL) return 1;
66         i = 0;
67         if (__wgetmainargs(&wargc, &wargv, &wenv, 1, &i) != 0) return 1;
68         if ((utf8argv = (char **)malloc(wargc*sizeof(char*))) == NULL) return 1;
69         ret = 0;
70
71         for (i=0; i<wargc; i++) {
72                 if ((utf8argv[i] = utf8_from_wchar(wargv[i])) == NULL) {
73                         ret = 1;
74                         break;
75                 }
76                 if (ret != 0) break;
77         }
78
79         if (ret == 0) {
80                 *argc = wargc;
81                 *argv = utf8argv;
82         } else {
83                 free(utf8argv);
84         }
85
86         return ret;
87 }
88
89 /* print functions */
90
91 int printf_utf8(const char *format, ...)
92 {
93         char *utmp = NULL;
94         wchar_t *wout = NULL;
95         int ret = -1;
96
97         while (1) {
98                 va_list argptr;
99                 if (!(utmp = (char *)malloc(32768*sizeof(char)))) break;
100                 va_start(argptr, format);
101                 ret = vsprintf(utmp, format, argptr);
102                 va_end(argptr);
103                 if (ret < 0) break;
104                 if (!(wout = wchar_from_utf8(utmp))) {
105                         ret = -1;
106                         break;
107                 }
108                 ret = wprintf(L"%s", wout);
109                 break;
110         }
111         if (utmp) free(utmp);
112         if (wout) free(wout);
113
114         return ret;
115 }
116
117 int fprintf_utf8(FILE *stream, const char *format, ...)
118 {
119         char *utmp = NULL;
120         wchar_t *wout = NULL;
121         int ret = -1;
122
123         while (1) {
124                 va_list argptr;
125                 if (!(utmp = (char *)malloc(32768*sizeof(char)))) break;
126                 va_start(argptr, format);
127                 ret = vsprintf(utmp, format, argptr);
128                 va_end(argptr);
129                 if (ret < 0) break;
130                 if (!(wout = wchar_from_utf8(utmp))) {
131                         ret = -1;
132                         break;
133                 }
134                 ret = fwprintf(stream, L"%s", wout);
135                 break;
136         }
137         if (utmp) free(utmp);
138         if (wout) free(wout);
139
140         return ret;
141 }
142
143 int vfprintf_utf8(FILE *stream, const char *format, va_list argptr)
144 {
145         char *utmp = NULL;
146         wchar_t *wout = NULL;
147         int ret = -1;
148
149         while (1) {
150                 if (!(utmp = (char *)malloc(32768*sizeof(char)))) break;
151                 if ((ret = vsprintf(utmp, format, argptr)) < 0) break;
152                 if (!(wout = wchar_from_utf8(utmp))) {
153                         ret = -1;
154                         break;
155                 }
156                 ret = fwprintf(stream, L"%s", wout);
157                 break;
158         }
159         if (utmp) free(utmp);
160         if (wout) free(wout);
161
162         return ret;
163 }
164
165 /* file functions */
166
167 FILE *fopen_utf8(const char *filename, const char *mode)
168 {
169         wchar_t *wname = NULL;
170         wchar_t *wmode = NULL;
171         FILE *f = NULL;
172
173         while (1) {
174                 if (!(wname = wchar_from_utf8(filename))) break;
175                 if (!(wmode = wchar_from_utf8(mode))) break;
176                 f = _wfopen(wname, wmode);
177                 break;
178         }
179         if (wname) free(wname);
180         if (wmode) free(wmode);
181
182         return f;
183 }
184
185 int _stat64_utf8(const char *path, struct _stat64 *buffer)
186 {
187         wchar_t *wpath;
188         int ret;
189
190         if (!(wpath = wchar_from_utf8(path))) return -1;
191         ret = _wstat64(wpath, buffer);
192         free(wpath);
193
194         return ret;
195 }
196
197 int chmod_utf8(const char *filename, int pmode)
198 {
199         wchar_t *wname;
200         int ret;
201
202         if (!(wname = wchar_from_utf8(filename))) return -1;
203         ret = _wchmod(wname, pmode);
204         free(wname);
205
206         return ret;
207 }
208
209 int utime_utf8(const char *filename, struct utimbuf *times)
210 {
211         wchar_t *wname;
212         struct _utimbuf ut;
213         int ret;
214
215         if (!(wname = wchar_from_utf8(filename))) return -1;
216         ret = _wutime(wname, &ut);
217         free(wname);
218
219         if (ret != -1) {
220                 if (sizeof(*times) == sizeof(ut)) {
221                         memcpy(times, &ut, sizeof(ut));
222                 } else {
223                         times->actime = ut.actime;
224                         times->modtime = ut.modtime;
225                 }
226         }
227
228         return ret;
229 }
230
231 int unlink_utf8(const char *filename)
232 {
233         wchar_t *wname;
234         int ret;
235
236         if (!(wname = wchar_from_utf8(filename))) return -1;
237         ret = _wunlink(wname);
238         free(wname);
239
240         return ret;
241 }
242
243 int rename_utf8(const char *oldname, const char *newname)
244 {
245         wchar_t *wold = NULL;
246         wchar_t *wnew = NULL;
247         int ret = -1;
248
249         while (1) {
250                 if (!(wold = wchar_from_utf8(oldname))) break;
251                 if (!(wnew = wchar_from_utf8(newname))) break;
252                 ret = _wrename(wold, wnew);
253                 break;
254         }
255         if (wold) free(wold);
256         if (wnew) free(wnew);
257
258         return ret;
259 }