win32: change _wfopen() -> wfsopen()
[fdkaac.git] / src / compat_win32.c
1 /*
2 * Copyright (C) 2013 nu774
3 * For conditions of distribution and use, see copyright notice in COPYING
4 */
5 #if HAVE_CONFIG_H
6 # include "config.h"
7 #endif
8 #if HAVE_STDINT_H
9 # include <stdint.h>
10 #endif
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <stdarg.h>
15 #include <assert.h>
16 #include <io.h>
17 #include <fcntl.h>
18 #include <share.h>
19 #include <sys/timeb.h>
20 #include "compat.h"
21 #define WIN32_LEAN_AND_MEAN
22 #include <windows.h>
23
24 typedef struct
25 {
26 int newmode;
27 } _startupinfo;
28
29 extern
30 int __wgetmainargs(int *, wchar_t ***, wchar_t ***, int, _startupinfo *);
31
32 int64_t aacenc_timer(void)
33 {
34 struct __timeb64 tv;
35 _ftime64(&tv);
36 return (int64_t)tv.time * 1000 + tv.millitm;
37 }
38
39 static
40 int codepage_decode_wchar(int codepage, const char *from, wchar_t **to)
41 {
42 int nc = MultiByteToWideChar(codepage, 0, from, -1, 0, 0);
43 if (nc == 0)
44 return -1;
45 *to = malloc(nc * sizeof(wchar_t));
46 MultiByteToWideChar(codepage, 0, from, -1, *to, nc);
47 return 0;
48 }
49
50 static
51 int codepage_encode_wchar(int codepage, const wchar_t *from, char **to)
52 {
53 int nc = WideCharToMultiByte(codepage, 0, from, -1, 0, 0, 0, 0);
54 if (nc == 0)
55 return -1;
56 *to = malloc(nc);
57 WideCharToMultiByte(codepage, 0, from, -1, *to, nc, 0, 0);
58 return 0;
59 }
60
61 FILE *aacenc_fopen(const char *name, const char *mode)
62 {
63 wchar_t *wname, *wmode;
64 FILE *fp;
65
66 if (strcmp(name, "-") == 0) {
67 fp = (mode[0] == 'r') ? stdin : stdout;
68 _setmode(_fileno(fp), _O_BINARY);
69 } else {
70 int share = _SH_DENYRW;
71 if (strchr(mode, 'r') && !strchr(mode, '+'))
72 share = _SH_DENYWR;
73 codepage_decode_wchar(CP_UTF8, name, &wname);
74 codepage_decode_wchar(CP_UTF8, mode, &wmode);
75 fp = _wfsopen(wname, wmode, share);
76 free(wname);
77 free(wmode);
78 }
79 return fp;
80 }
81
82 static char **__aacenc_argv__;
83
84 static
85 void aacenc_free_mainargs(void)
86 {
87 char **p = __aacenc_argv__;
88 for (; *p; ++p)
89 free(*p);
90 free(__aacenc_argv__);
91 }
92
93 void aacenc_getmainargs(int *argc, char ***argv)
94 {
95 int i;
96 wchar_t **wargv, **envp;
97 _startupinfo si = { 0 };
98
99 __wgetmainargs(argc, &wargv, &envp, 1, &si);
100 *argv = malloc((*argc + 1) * sizeof(char*));
101 for (i = 0; i < *argc; ++i)
102 codepage_encode_wchar(CP_UTF8, wargv[i], &(*argv)[i]);
103 (*argv)[*argc] = 0;
104 __aacenc_argv__ = *argv;
105 atexit(aacenc_free_mainargs);
106 }
107
108 char *aacenc_to_utf8(const char *s)
109 {
110 return _strdup(s);
111 }
112
113 #if defined(__MINGW32__) && !defined(HAVE__VSCPRINTF)
114 int _vscprintf(const char *fmt, va_list ap)
115 {
116 static int (*fp_vscprintf)(const char *, va_list) = 0;
117 if (!fp_vscprintf) {
118 HANDLE h = GetModuleHandleA("msvcrt.dll");
119 FARPROC fp = GetProcAddress(h, "_vscprintf");
120 InterlockedCompareExchangePointer(&fp_vscprintf, fp, 0);
121 }
122 assert(fp_vscprintf);
123 return fp_vscprintf(fmt, ap);
124 }
125 #endif
126
127 int aacenc_fprintf(FILE *fp, const char *fmt, ...)
128 {
129 va_list ap;
130 int cnt;
131 HANDLE fh = (HANDLE)_get_osfhandle(_fileno(fp));
132
133 if (GetFileType(fh) != FILE_TYPE_CHAR) {
134 va_start(ap, fmt);
135 cnt = vfprintf(fp, fmt, ap);
136 va_end(ap);
137 } else {
138 char *s;
139 wchar_t *ws;
140 DWORD nw;
141
142 va_start(ap, fmt);
143 cnt = _vscprintf(fmt, ap);
144 va_end(ap);
145
146 s = malloc(cnt + 1);
147
148 va_start(ap, fmt);
149 cnt = _vsnprintf(s, cnt + 1, fmt, ap);
150 va_end(ap);
151
152 codepage_decode_wchar(CP_UTF8, s, &ws);
153 free(s);
154 fflush(fp);
155 WriteConsoleW(fh, ws, cnt, &nw, 0);
156 free(ws);
157 }
158 return cnt;
159 }
160
161 const char *aacenc_basename(const char *path)
162 {
163 /*
164 * Since path is encoded with UTF-8, naive usage of strrchr() shoule be safe.
165 */
166 const char *p = strrchr(path, '/');
167 const char *q = strrchr(path, '\\');
168 const char *r = strrchr(path, ':');
169 if (q > p) p = q;
170 if (r > p) p = r;
171 return p ? p + 1 : path;
172 }
This page took 0.025682 seconds and 4 git commands to generate.