diff options
author | Erik de Castro Lopo <erikd@mega-nerd.com> | 2016-02-04 13:42:33 +1100 |
---|---|---|
committer | Erik de Castro Lopo <erikd@mega-nerd.com> | 2016-02-08 13:43:00 +1100 |
commit | a5c8e8e14de182c4e8c5a8cd0b6be7c75ab6f021 (patch) | |
tree | 7f2277fc3e3be382f600e50dd9fb2dadd2278d93 | |
parent | b821ac2dad2c0cf8dcd9915d16fd6222c1618fbc (diff) | |
download | flac-a5c8e8e14de182c4e8c5a8cd0b6be7c75ab6f021.tar.gz |
src/share/utf8/utf8.c: Windows API usage fixes
Patch-from: <lvqcl.mail@gmail.com>
-rw-r--r-- | src/share/utf8/utf8.c | 265 |
1 files changed, 74 insertions, 191 deletions
diff --git a/src/share/utf8/utf8.c b/src/share/utf8/utf8.c index 093067cb..0519d8e1 100644 --- a/src/share/utf8/utf8.c +++ b/src/share/utf8/utf8.c @@ -4,6 +4,8 @@ * * Buffer overflow checking added: Josh Coalson, 9/9/2007 * + * Win32 part rewritten: lvqcl, 2/2/2016 + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -28,220 +30,98 @@ #endif #include <stdlib.h> -#include <string.h> #include "share/alloc.h" -#include "share/safe_str.h" #include "share/utf8.h" - #ifdef _WIN32 - /* Thanks to Peter Harris <peter.harris@hummingbird.com> for this win32 - * code. - */ - -#include <stdio.h> #include <windows.h> -static unsigned char *make_utf8_string(const wchar_t *unicode) +int utf8_encode(const char *from, char **to) { - size_t size = 0, n; - int indx = 0, out_index = 0; - unsigned char *out; - unsigned short c; - - /* first calculate the size of the target string */ - c = unicode[indx++]; - while(c) { - if(c < 0x0080) { - n = 1; - } else if(c < 0x0800) { - n = 2; - } else { - n = 3; - } - if(size+n < size) /* overflow check */ - return NULL; - size += n; - c = unicode[indx++]; - } - - out = safe_malloc_add_2op_(size, /*+*/1); - if (out == NULL) - return NULL; - indx = 0; - - c = unicode[indx++]; - while(c) - { - if(c < 0x080) { - out[out_index++] = (unsigned char)c; - } else if(c < 0x800) { - out[out_index++] = 0xc0 | (c >> 6); - out[out_index++] = 0x80 | (c & 0x3f); - } else { - out[out_index++] = 0xe0 | (c >> 12); - out[out_index++] = 0x80 | ((c >> 6) & 0x3f); - out[out_index++] = 0x80 | (c & 0x3f); - } - c = unicode[indx++]; - } - out[out_index] = 0x00; - - return out; -} + wchar_t *unicode = NULL; + char *utf8 = NULL; + int ret = -1; -static wchar_t *make_unicode_string(const unsigned char *utf8) -{ - size_t size = 0; - int indx = 0, out_index = 0; - wchar_t *out; - unsigned char c; - - /* first calculate the size of the target string */ - c = utf8[indx++]; - while(c) { - if((c & 0x80) == 0) { - indx += 0; - } else if((c & 0xe0) == 0xe0) { - indx += 2; - } else { - indx += 1; - } - if(size + 1 == 0) /* overflow check */ - return NULL; - size++; - c = utf8[indx++]; - } - - if(size + 1 == 0) /* overflow check */ - return NULL; - out = safe_malloc_mul_2op_(size+1, /*times*/sizeof(wchar_t)); - if (out == NULL) - return NULL; - indx = 0; - - c = utf8[indx++]; - while(c) - { - if((c & 0x80) == 0) { - out[out_index++] = c; - } else if((c & 0xe0) == 0xe0) { - out[out_index] = (c & 0x1F) << 12; - c = utf8[indx++]; - out[out_index] |= (c & 0x3F) << 6; - c = utf8[indx++]; - out[out_index++] |= (c & 0x3F); - } else { - out[out_index] = (c & 0x3F) << 6; - c = utf8[indx++]; - out[out_index++] |= (c & 0x3F); - } - c = utf8[indx++]; - } - out[out_index] = 0; - - return out; -} + do { + int len; -int utf8_encode(const char *from, char **to) -{ - wchar_t *unicode; - int wchars, err; + len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, -1, NULL, 0); + if(len == 0) break; - wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, - strlen(from), NULL, 0); + unicode = (wchar_t*) safe_malloc_mul_2op_((size_t)len, sizeof(wchar_t)); + if(unicode == NULL) break; - if(wchars == 0) - { - fprintf(stderr, "Unicode translation error %d\n", (int)GetLastError()); - return -1; - } + len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, -1, unicode, len); + if(len == 0) break; - if(wchars < 0) /* underflow check */ - return -1; + len = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, NULL, 0, NULL, NULL); + if(len == 0) break; - unicode = safe_calloc_((size_t)wchars + 1, sizeof(unsigned short)); - if(unicode == NULL) - { - fprintf(stderr, "Out of memory processing string to UTF8\n"); - return -1; - } + utf8 = (char*) safe_malloc_mul_2op_((size_t)len, sizeof(char)); + if(utf8 == NULL) break; + + len = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, utf8, len, NULL, NULL); + if(len == 0) break; - err = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, - strlen(from), unicode, wchars); - if(err != wchars) - { - free(unicode); - fprintf(stderr, "Unicode translation error %d\n", (int)GetLastError()); - return -1; - } + ret = 0; + + } while(0); + + free(unicode); - /* On NT-based windows systems, we could use WideCharToMultiByte(), but - * MS doesn't actually have a consistent API across win32. - */ - *to = (char*)make_utf8_string(unicode); - if(*to == NULL) - { - free(unicode); - fprintf(stderr, "Out of memory processing string from UNICODE16 to UTF8\n"); - return -1; + if(ret == 0) { + *to = utf8; + } else { + free(utf8); + *to = NULL; } - free(unicode); - return 0; + return ret; } int utf8_decode(const char *from, char **to) { - wchar_t *unicode; - int chars, err; - - /* On NT-based windows systems, we could use MultiByteToWideChar(CP_UTF8), but - * MS doesn't actually have a consistent API across win32. - */ - unicode = make_unicode_string((const unsigned char*)from); - if(unicode == NULL) - { - fprintf(stderr, "Out of memory processing string from UTF8 to UNICODE16\n"); - return -1; - } - - chars = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, - -1, NULL, 0, NULL, NULL); - - if(chars < 0) /* underflow check */ - return -1; - - if(chars == 0) - { - fprintf(stderr, "Unicode translation error %d\n", (int)GetLastError()); - free(unicode); - return -1; - } - - *to = safe_calloc_((size_t)chars + 1, sizeof(unsigned char)); - if(*to == NULL) - { - fprintf(stderr, "Out of memory processing string to local charset\n"); - free(unicode); - return -1; - } - - err = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, - -1, *to, chars, NULL, NULL); - if(err != chars) - { - fprintf(stderr, "Unicode translation error %d\n", (int)GetLastError()); - free(unicode); - free(*to); - *to = NULL; - return -1; - } - - free(unicode); - return 0; + wchar_t *unicode = NULL; + char *acp = NULL; + int ret = -1; + + do { + int len; + + len = MultiByteToWideChar(CP_UTF8, 0, from, -1, NULL, 0); + if(len == 0) break; + + unicode = (wchar_t*) safe_malloc_mul_2op_((size_t)len, sizeof(wchar_t)); + if(unicode == NULL) break; + + len = MultiByteToWideChar(CP_UTF8, 0, from, -1, unicode, len); + if(len == 0) break; + + len = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, NULL, 0, NULL, NULL); + if(len == 0) break; + + acp = (char*) safe_malloc_mul_2op_((size_t)len, sizeof(char)); + if(acp == NULL) break; + + len = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, acp, len, NULL, NULL); + if(len == 0) break; + + ret = 0; + + } while(0); + + free(unicode); + + if(ret == 0) { + *to = acp; + } else { + free(acp); + *to = NULL; + } + + return ret; } #else /* End win32. Rest is for real operating systems */ @@ -251,6 +131,9 @@ int utf8_decode(const char *from, char **to) #include <langinfo.h> #endif +#include <string.h> + +#include "share/safe_str.h" #include "iconvert.h" #include "charset.h" |