[FFmpeg-devel] [PATCH] avutil/log: in colored_fputs, convert string from utf8 to CP_ACP charset on Windows

Nicolas George george at nsup.org
Fri Feb 21 10:13:59 CET 2014


Le tridi 3 ventôse, an CCXXII, 周泽华 a écrit :
> diff --git a/libavutil/log.c b/libavutil/log.c
> index 38ce1e8..c779d64 100644
> --- a/libavutil/log.c
> +++ b/libavutil/log.c
> @@ -50,6 +50,10 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
>  static int av_log_level = AV_LOG_INFO;
>  static int flags;
>  
> +#if HAVE_MULTIBYTETOWIDECHAR && HAVE_WIDECHARTOMULTIBYTE
> +#include<windows.h>
> +#endif
> +
>  #if HAVE_SETCONSOLETEXTATTRIBUTE
>  #include <windows.h>
>  static const uint8_t color[16 + AV_CLASS_CATEGORY_NB] = {
> @@ -101,11 +105,55 @@ static const uint32_t color[16 + AV_CLASS_CATEGORY_NB] = {
>  #endif
>  static int use_color = -1;
>  
> +#if HAVE_MULTIBYTETOWIDECHAR && HAVE_WIDECHARTOMULTIBYTE
> +int is_stderr_redirected()
> +{
> +    HANDLE stderr_handle;
> +    DWORD file_type, num;
> +
> +    stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
> +    if (stderr_handle == INVALID_HANDLE_VALUE)
> +        return 1;
> +    file_type = GetFileType(stderr_handle);
> +    if ((file_type & FILE_TYPE_CHAR) != FILE_TYPE_CHAR)
> +        return 1;
> +    return !GetConsoleMode(stderr_handle, &num);
> +}
> +#endif
> +
>  static void colored_fputs(int level, const char *str)
>  {
> +#if HAVE_MULTIBYTETOWIDECHAR && HAVE_WIDECHARTOMULTIBYTE
> +    int num_wchars, num_chars;
> +    wchar_t *wstr = NULL;
> +    char *str_acp = NULL; /* str in CP_ACP charset */
> +#endif
> +
>      if (!*str)
>          return;
>  
> +#if HAVE_MULTIBYTETOWIDECHAR && HAVE_WIDECHARTOMULTIBYTE
> +    if (is_stderr_redirected())
> +        goto no_acp_conversion;
> +
> +    /* convert UTF-8 to wide chars, and then convert wide chars to CP_ACP */
> +    num_wchars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, NULL, 0);
> +    if (num_wchars > 0) {
> +        wstr = av_mallocz(sizeof(wchar_t) * num_wchars);
> +        if (wstr) {
> +            MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, num_wchars);
> +            num_chars = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL ,NULL);
> +            str_acp = av_mallocz(sizeof(char) * num_chars);
> +            if (str_acp) {
> +                WideCharToMultiByte(CP_ACP, 0, wstr, -1, str_acp, num_chars, NULL, NULL);
> +                str = str_acp;
> +            }
> +            av_freep(&wstr);
> +        }
> +    }
> +no_acp_conversion:
> +#endif
> +
>      if (use_color < 0) {
>  #if HAVE_SETCONSOLETEXTATTRIBUTE
>          CONSOLE_SCREEN_BUFFER_INFO con_info;
> @@ -152,6 +200,11 @@ static void colored_fputs(int level, const char *str)
>          fputs(str, stderr);
>  #endif
>  
> +#if HAVE_MULTIBYTETOWIDECHAR && HAVE_WIDECHARTOMULTIBYTE
> +    if (str_acp) {
> +        av_freep(&str_acp);
> +    }
> +#endif
>  }
>  
>  const char *av_default_item_name(void *ptr)

I do not know if this patch does the right thing; in fact I do not care much
about windows. But from a stylistic point of view, I would suggest to group
everything system-dependant into a single function, to reduce the #if
cruft. Something like that:

 colored_fputs()
 {
+    char to_free = NULL;
     ...
+    recode_for_console(&str, &to_free);
     ...
+    free(to_free);
 }

And the function itself:

void recode_for_console(char **str, char **to_free)
{
#if HAVE_*
    test if stderr is redirected
    if (it is)
        return; /* do nothing */
    do the conversion
    *to_free = converted_string;
    *str = converted_string;
#endif /* otherwise, do nothing */
}

Regards,

-- 
  Nicolas George
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20140221/87af6122/attachment.asc>


More information about the ffmpeg-devel mailing list