mirror of https://github.com/mpv-player/mpv
win32: add getenv() UTF-8 variant
This is a bit "hard", because getenv() returns a static string, and we can't just return an allocated string. We also want getenv() to be thread-safe if possible. (If the mpv core is going to be more threaded, we sure do want the lower layers to be thread-safe as well.)
This commit is contained in:
parent
b97d10a839
commit
12372298a2
60
osdep/io.c
60
osdep/io.c
|
@ -58,6 +58,12 @@ char *mp_to_utf8(void *talloc_ctx, const wchar_t *s)
|
|||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef HAVE_PTHREADS
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "mpvcore/mp_talloc.h"
|
||||
|
||||
//http://git.libav.org/?p=libav.git;a=blob;f=cmdutils.c;h=ade3f10ce2fc030e32e375a85fbd06c26d43a433#l161
|
||||
|
||||
static char** win32_argv_utf8;
|
||||
|
@ -255,4 +261,58 @@ int mp_mkdir(const char *path, int mode)
|
|||
return res;
|
||||
}
|
||||
|
||||
static char **utf8_environ;
|
||||
static void *utf8_environ_ctx;
|
||||
|
||||
static void free_env(void)
|
||||
{
|
||||
talloc_free(utf8_environ_ctx);
|
||||
utf8_environ_ctx = NULL;
|
||||
utf8_environ = NULL;
|
||||
}
|
||||
|
||||
// Note: UNIX getenv() returns static strings, and we try to do the same. Since
|
||||
// using putenv() is not multithreading safe, we don't expect env vars to change
|
||||
// at runtime, and converting/allocating them in advance is ok.
|
||||
static void init_getenv(void)
|
||||
{
|
||||
if (utf8_environ_ctx)
|
||||
return;
|
||||
wchar_t *wenv = GetEnvironmentStringsW();
|
||||
if (!wenv)
|
||||
return;
|
||||
utf8_environ_ctx = talloc_new(NULL);
|
||||
int num_env = 0;
|
||||
while (1) {
|
||||
size_t len = wcslen(wenv);
|
||||
if (!len)
|
||||
break;
|
||||
char *s = mp_to_utf8(utf8_environ_ctx, wenv);
|
||||
MP_TARRAY_APPEND(utf8_environ_ctx, utf8_environ, num_env, s);
|
||||
wenv += len + 1;
|
||||
}
|
||||
MP_TARRAY_APPEND(utf8_environ_ctx, utf8_environ, num_env, NULL);
|
||||
// Avoid showing up in leak detectors etc.
|
||||
atexit(free_env);
|
||||
}
|
||||
|
||||
char *mp_getenv(const char *name)
|
||||
{
|
||||
#ifdef HAVE_PTHREADS
|
||||
static pthread_once_t once_init_getenv = PTHREAD_ONCE_INIT;
|
||||
pthread_once(&once_init_getenv, init_getenv);
|
||||
#else
|
||||
init_getenv();
|
||||
#endif
|
||||
// Copied from musl, http://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
|
||||
// Copyright © 2005-2013 Rich Felker, standard MIT license
|
||||
int i;
|
||||
size_t l = strlen(name);
|
||||
if (!utf8_environ || !*name || strchr(name, '=')) return NULL;
|
||||
for (i=0; utf8_environ[i] && (strncmp(name, utf8_environ[i], l)
|
||||
|| utf8_environ[i][l] != '='); i++) {}
|
||||
if (utf8_environ[i]) return utf8_environ[i] + l+1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // __MINGW32__
|
||||
|
|
|
@ -59,6 +59,7 @@ DIR *mp_opendir(const char *path);
|
|||
struct dirent *mp_readdir(DIR *dir);
|
||||
int mp_closedir(DIR *dir);
|
||||
int mp_mkdir(const char *path, int mode);
|
||||
char *mp_getenv(const char *name);
|
||||
|
||||
// NOTE: stat is not overridden with mp_stat, because MinGW-w64 defines it as
|
||||
// macro.
|
||||
|
@ -72,6 +73,7 @@ int mp_mkdir(const char *path, int mode);
|
|||
#define readdir(...) mp_readdir(__VA_ARGS__)
|
||||
#define closedir(...) mp_closedir(__VA_ARGS__)
|
||||
#define mkdir(...) mp_mkdir(__VA_ARGS__)
|
||||
#define getenv(...) mp_getenv(__VA_ARGS__)
|
||||
|
||||
#else /* __MINGW32__ */
|
||||
|
||||
|
|
Loading…
Reference in New Issue