gsmopen: added win_iconv
This commit is contained in:
parent
3747375196
commit
3df7a04df5
|
@ -0,0 +1,72 @@
|
|||
|
||||
# comma separated list (e.g. "iconv.dll,libiconv.dll")
|
||||
DEFAULT_LIBICONV_DLL ?= \"\"
|
||||
|
||||
CFLAGS += -pedantic -Wall
|
||||
CFLAGS += -DUSE_LIBICONV_DLL
|
||||
CFLAGS += -DDEFAULT_LIBICONV_DLL=$(DEFAULT_LIBICONV_DLL)
|
||||
|
||||
all: iconv.dll libiconv.a win_iconv.exe
|
||||
|
||||
dist: test win_iconv.zip
|
||||
|
||||
iconv.dll: win_iconv.c
|
||||
gcc $(CFLAGS) -c win_iconv.c -DMAKE_DLL
|
||||
dllwrap --dllname iconv.dll --def iconv.def win_iconv.o $(SPECS_FLAGS)
|
||||
strip iconv.dll
|
||||
|
||||
libiconv.a: win_iconv.c
|
||||
gcc $(CFLAGS) -c win_iconv.c
|
||||
ar rcs libiconv.a win_iconv.o
|
||||
ranlib libiconv.a
|
||||
|
||||
win_iconv.exe: win_iconv.c
|
||||
gcc $(CFLAGS) -s -o win_iconv.exe win_iconv.c -DMAKE_EXE
|
||||
|
||||
libmlang.a: mlang.def
|
||||
dlltool --kill-at --input-def mlang.def --output-lib libmlang.a
|
||||
|
||||
test:
|
||||
gcc $(CFLAGS) -s -o win_iconv_test.exe win_iconv_test.c
|
||||
./win_iconv_test.exe
|
||||
|
||||
win_iconv.zip: msvcrt msvcr70 msvcr71
|
||||
rm -rf win_iconv
|
||||
svn export . win_iconv
|
||||
cp msvcrt/iconv.dll msvcrt/win_iconv.exe win_iconv/
|
||||
mkdir win_iconv/msvcr70
|
||||
cp msvcr70/iconv.dll win_iconv/msvcr70/
|
||||
mkdir win_iconv/msvcr71
|
||||
cp msvcr71/iconv.dll win_iconv/msvcr71/
|
||||
zip -r win_iconv.zip win_iconv
|
||||
|
||||
msvcrt:
|
||||
svn export . msvcrt; \
|
||||
cd msvcrt; \
|
||||
$(MAKE);
|
||||
|
||||
msvcr70:
|
||||
svn export . msvcr70; \
|
||||
cd msvcr70; \
|
||||
gcc -dumpspecs | sed s/-lmsvcrt/-lmsvcr70/ > specs; \
|
||||
$(MAKE) "SPECS_FLAGS=-specs=$$PWD/specs";
|
||||
|
||||
msvcr71:
|
||||
svn export . msvcr71; \
|
||||
cd msvcr71; \
|
||||
gcc -dumpspecs | sed s/-lmsvcrt/-lmsvcr71/ > specs; \
|
||||
$(MAKE) "SPECS_FLAGS=-specs=$$PWD/specs";
|
||||
|
||||
clean:
|
||||
rm -f win_iconv.exe
|
||||
rm -f win_iconv.o
|
||||
rm -f iconv.dll
|
||||
rm -f libiconv.a
|
||||
rm -f win_iconv_test.exe
|
||||
rm -f libmlang.a
|
||||
rm -rf win_iconv
|
||||
rm -rf win_iconv.zip
|
||||
rm -rf msvcrt
|
||||
rm -rf msvcr70
|
||||
rm -rf msvcr71
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
LIBRARY ICONV.DLL
|
||||
EXPORTS
|
||||
iconv
|
||||
iconv_open
|
||||
iconv_close
|
||||
iconvctl
|
||||
libiconv=iconv
|
||||
libiconv_open=iconv_open
|
||||
libiconv_close=iconv_close
|
||||
libiconvctl=iconvctl
|
||||
;; libiconv-1.11.dll
|
||||
;; TODO for binary compatibility
|
||||
; _libiconv_version @1
|
||||
; aliases2_lookup @2
|
||||
; aliases_lookup @3
|
||||
; iconv_canonicalize @4
|
||||
; libiconv @5
|
||||
; libiconv_close @6
|
||||
; libiconv_open @7
|
||||
; libiconv_relocate @8
|
||||
; libiconv_set_relocation_prefix @9
|
||||
; libiconvctl @10
|
||||
; libiconvlist @11
|
||||
; locale_charset @12
|
|
@ -0,0 +1,5 @@
|
|||
#include <stddef.h>
|
||||
typedef void* iconv_t;
|
||||
iconv_t iconv_open(const char *tocode, const char *fromcode);
|
||||
int iconv_close(iconv_t cd);
|
||||
size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
|
|
@ -0,0 +1,11 @@
|
|||
LIBRARY MLANG.DLL
|
||||
EXPORTS
|
||||
ConvertINetMultiByteToUnicode@24
|
||||
;; ConvertINetReset (not documented)
|
||||
ConvertINetString@28
|
||||
ConvertINetUnicodeToMultiByte@24
|
||||
IsConvertINetStringAvailable@8
|
||||
LcidToRfc1766A@12
|
||||
LcidToRfc1766W@12
|
||||
Rfc1766ToLcidA@8
|
||||
Rfc1766ToLcidW@8
|
|
@ -0,0 +1,54 @@
|
|||
HRESULT WINAPI ConvertINetString(
|
||||
LPDWORD lpdwMode,
|
||||
DWORD dwSrcEncoding,
|
||||
DWORD dwDstEncoding,
|
||||
LPCSTR lpSrcStr,
|
||||
LPINT lpnSrcSize,
|
||||
LPBYTE lpDstStr,
|
||||
LPINT lpnDstSize
|
||||
);
|
||||
|
||||
HRESULT WINAPI ConvertINetMultiByteToUnicode(
|
||||
LPDWORD lpdwMode,
|
||||
DWORD dwSrcEncoding,
|
||||
LPCSTR lpSrcStr,
|
||||
LPINT lpnMultiCharCount,
|
||||
LPWSTR lpDstStr,
|
||||
LPINT lpnWideCharCount
|
||||
);
|
||||
|
||||
HRESULT WINAPI ConvertINetUnicodeToMultiByte(
|
||||
LPDWORD lpdwMode,
|
||||
DWORD dwEncoding,
|
||||
LPCWSTR lpSrcStr,
|
||||
LPINT lpnWideCharCount,
|
||||
LPSTR lpDstStr,
|
||||
LPINT lpnMultiCharCount
|
||||
);
|
||||
|
||||
HRESULT WINAPI IsConvertINetStringAvailable(
|
||||
DWORD dwSrcEncoding,
|
||||
DWORD dwDstEncoding
|
||||
);
|
||||
|
||||
HRESULT WINAPI LcidToRfc1766A(
|
||||
LCID Locale,
|
||||
LPSTR pszRfc1766,
|
||||
int nChar
|
||||
);
|
||||
|
||||
HRESULT WINAPI LcidToRfc1766W(
|
||||
LCID Locale,
|
||||
LPWSTR pszRfc1766,
|
||||
int nChar
|
||||
);
|
||||
|
||||
HRESULT WINAPI Rfc1766ToLcidA(
|
||||
LCID *pLocale,
|
||||
LPSTR pszRfc1766
|
||||
);
|
||||
|
||||
HRESULT WINAPI Rfc1766ToLcidW(
|
||||
LCID *pLocale,
|
||||
LPWSTR pszRfc1766
|
||||
);
|
|
@ -0,0 +1,3 @@
|
|||
win_iconv is a iconv library using Win32 API to conversion.
|
||||
win_iconv is placed in the public domain.
|
||||
Yukihiro Nakadaira <yukihiro.nakadaira@gmail.com>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,261 @@
|
|||
|
||||
#include "win_iconv.c"
|
||||
#include <stdio.h>
|
||||
|
||||
const char *
|
||||
tohex(const char *str, int size)
|
||||
{
|
||||
static char buf[BUFSIZ];
|
||||
char *pbuf = buf;
|
||||
int i;
|
||||
buf[0] = 0;
|
||||
for (i = 0; i < size; ++i)
|
||||
pbuf += sprintf(pbuf, "%02X", str[i] & 0xFF);
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *
|
||||
errstr(int errcode)
|
||||
{
|
||||
static char buf[BUFSIZ];
|
||||
switch (errcode)
|
||||
{
|
||||
case 0: return "NOERROR";
|
||||
case EINVAL: return "EINVAL";
|
||||
case EILSEQ: return "EILSEQ";
|
||||
case E2BIG: return "E2BIG";
|
||||
}
|
||||
sprintf(buf, "%d\n", errcode);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#ifdef USE_LIBICONV_DLL
|
||||
int use_dll;
|
||||
|
||||
int
|
||||
setdll(const char *dllpath)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
rec_iconv_t cd;
|
||||
|
||||
sprintf(buf, "WINICONV_LIBICONV_DLL=%s", dllpath);
|
||||
putenv(buf);
|
||||
if (libiconv_iconv_open(&cd, "ascii", "ascii"))
|
||||
{
|
||||
FreeLibrary(cd.hlibiconv);
|
||||
use_dll = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
use_dll = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We can test the codepage that is installed in the system.
|
||||
*/
|
||||
int
|
||||
check_enc(const char *encname, int codepage)
|
||||
{
|
||||
iconv_t cd;
|
||||
int cp;
|
||||
cd = iconv_open("utf-8", encname);
|
||||
if (cd == (iconv_t)(-1))
|
||||
{
|
||||
printf("%s(%d) IS NOT SUPPORTED: SKIP THE TEST\n", encname, codepage);
|
||||
return FALSE;
|
||||
}
|
||||
cp = ((rec_iconv_t *)cd)->from.codepage;
|
||||
if (cp != codepage)
|
||||
{
|
||||
printf("%s(%d) ALIAS IS MAPPED TO DIFFERENT CODEPAGE (%d)\n", encname, codepage, cp);
|
||||
exit(1);
|
||||
}
|
||||
iconv_close(cd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int use_dll;
|
||||
|
||||
void
|
||||
test(const char *from, const char *fromstr, int fromsize, const char *to, const char *tostr, int tosize, int errcode, int bufsize, int line)
|
||||
{
|
||||
char outbuf[BUFSIZ];
|
||||
const char *pin;
|
||||
char *pout;
|
||||
size_t inbytesleft;
|
||||
size_t outbytesleft;
|
||||
iconv_t cd;
|
||||
size_t r;
|
||||
char dllpath[_MAX_PATH];
|
||||
|
||||
cd = iconv_open(to, from);
|
||||
if (cd == (iconv_t)(-1))
|
||||
{
|
||||
printf("%s -> %s: NG: INVALID ENCODING NAME: line=%d\n", from, to, line);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef USE_LIBICONV_DLL
|
||||
if (((rec_iconv_t *)cd)->hlibiconv != NULL)
|
||||
GetModuleFileName(((rec_iconv_t *)cd)->hlibiconv, dllpath, sizeof(dllpath));
|
||||
|
||||
if (use_dll && ((rec_iconv_t *)cd)->hlibiconv == NULL)
|
||||
{
|
||||
printf("%s: %s -> %s: NG: FAILED TO USE DLL: line=%d\n", dllpath, from, to, line);
|
||||
exit(1);
|
||||
}
|
||||
else if (!use_dll && ((rec_iconv_t *)cd)->hlibiconv != NULL)
|
||||
{
|
||||
printf("%s: %s -> %s: NG: DLL IS LOADED UNEXPECTEDLY: line=%d\n", dllpath, from, to, line);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
errno = 0;
|
||||
|
||||
pin = fromstr;
|
||||
pout = outbuf;
|
||||
inbytesleft = fromsize;
|
||||
outbytesleft = bufsize;
|
||||
r = iconv(cd, &pin, &inbytesleft, &pout, &outbytesleft);
|
||||
if (r != (size_t)(-1))
|
||||
r = iconv(cd, NULL, NULL, &pout, &outbytesleft);
|
||||
*pout = 0;
|
||||
|
||||
#ifdef USE_LIBICONV_DLL
|
||||
if (use_dll)
|
||||
printf("%s: ", dllpath);
|
||||
#endif
|
||||
printf("%s(%s) -> ", from, tohex(fromstr, fromsize));
|
||||
printf("%s(%s%s%s): ", to, tohex(tostr, tosize),
|
||||
errcode == 0 ? "" : ":",
|
||||
errcode == 0 ? "" : errstr(errcode));
|
||||
if (strcmp(outbuf, tostr) == 0 && errno == errcode)
|
||||
printf("OK\n");
|
||||
else
|
||||
{
|
||||
printf("RESULT(%s:%s): ", tohex(outbuf, sizeof(outbuf) - outbytesleft),
|
||||
errstr(errno));
|
||||
printf("NG: line=%d\n", line);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#define STATIC_STRLEN(arr) (sizeof(arr) - 1)
|
||||
|
||||
#define success(from, fromstr, to, tostr) test(from, fromstr, STATIC_STRLEN(fromstr), to, tostr, STATIC_STRLEN(tostr), 0, BUFSIZ, __LINE__)
|
||||
#define einval(from, fromstr, to, tostr) test(from, fromstr, STATIC_STRLEN(fromstr), to, tostr, STATIC_STRLEN(tostr), EINVAL, BUFSIZ, __LINE__)
|
||||
#define eilseq(from, fromstr, to, tostr) test(from, fromstr, STATIC_STRLEN(fromstr), to, tostr, STATIC_STRLEN(tostr), EILSEQ, BUFSIZ, __LINE__)
|
||||
#define e2big(from, fromstr, to, tostr, bufsize) test(from, fromstr, STATIC_STRLEN(fromstr), to, tostr, STATIC_STRLEN(tostr), E2BIG, bufsize, __LINE__)
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
#ifdef USE_LIBICONV_DLL
|
||||
/* test use of dll if $DEFAULT_LIBICONV_DLL was defined. */
|
||||
if (setdll(""))
|
||||
{
|
||||
success("ascii", "ABC", "ascii", "ABC");
|
||||
success("ascii", "ABC", "utf-16be", "\x00\x41\x00\x42\x00\x43");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\nDLL TEST IS SKIPPED\n\n");
|
||||
}
|
||||
|
||||
setdll("none");
|
||||
#endif
|
||||
|
||||
if (check_enc("ascii", 20127))
|
||||
{
|
||||
success("ascii", "ABC", "ascii", "ABC");
|
||||
/* MSB is dropped. Hmm... */
|
||||
success("ascii", "\x80\xFF", "ascii", "\x00\x7F");
|
||||
}
|
||||
|
||||
/* unicode (CP1200 CP1201 CP12000 CP12001 CP65001) */
|
||||
if (check_enc("utf-8", 65001)
|
||||
&& check_enc("utf-16be", 1201) && check_enc("utf-16le", 1200)
|
||||
&& check_enc("utf-32be", 12001) && check_enc("utf-32le", 12000)
|
||||
)
|
||||
{
|
||||
/* Test the BOM behavior
|
||||
* 1. Remove the BOM when "fromcode" is utf-16 or utf-32.
|
||||
* 2. Add the BOM when "tocode" is utf-16 or utf-32. */
|
||||
success("utf-16", "\xFE\xFF\x01\x02", "utf-16be", "\x01\x02");
|
||||
success("utf-16", "\xFF\xFE\x02\x01", "utf-16be", "\x01\x02");
|
||||
success("utf-32", "\x00\x00\xFE\xFF\x00\x00\x01\x02", "utf-32be", "\x00\x00\x01\x02");
|
||||
success("utf-32", "\xFF\xFE\x00\x00\x02\x01\x00\x00", "utf-32be", "\x00\x00\x01\x02");
|
||||
success("utf-16", "\xFE\xFF\x00\x01", "utf-8", "\x01");
|
||||
#ifndef GLIB_COMPILATION
|
||||
success("utf-8", "\x01", "utf-16", "\xFE\xFF\x00\x01");
|
||||
success("utf-8", "\x01", "utf-32", "\x00\x00\xFE\xFF\x00\x00\x00\x01");
|
||||
#else
|
||||
success("utf-8", "\x01", "utf-16", "\xFF\xFE\x01\x00");
|
||||
success("utf-8", "\x01", "utf-32", "\xFF\xFE\x00\x00\x01\x00\x00\x00");
|
||||
#endif
|
||||
|
||||
success("utf-16be", "\xFE\xFF\x01\x02", "utf-16be", "\xFE\xFF\x01\x02");
|
||||
success("utf-16le", "\xFF\xFE\x02\x01", "utf-16be", "\xFE\xFF\x01\x02");
|
||||
success("utf-32be", "\x00\x00\xFE\xFF\x00\x00\x01\x02", "utf-32be", "\x00\x00\xFE\xFF\x00\x00\x01\x02");
|
||||
success("utf-32le", "\xFF\xFE\x00\x00\x02\x01\x00\x00", "utf-32be", "\x00\x00\xFE\xFF\x00\x00\x01\x02");
|
||||
success("utf-16be", "\xFE\xFF\x00\x01", "utf-8", "\xEF\xBB\xBF\x01");
|
||||
success("utf-8", "\xEF\xBB\xBF\x01", "utf-8", "\xEF\xBB\xBF\x01");
|
||||
|
||||
success("utf-16be", "\x01\x02", "utf-16le", "\x02\x01");
|
||||
success("utf-16le", "\x02\x01", "utf-16be", "\x01\x02");
|
||||
success("utf-16be", "\xFE\xFF", "utf-16le", "\xFF\xFE");
|
||||
success("utf-16le", "\xFF\xFE", "utf-16be", "\xFE\xFF");
|
||||
success("utf-32be", "\x00\x00\x03\x04", "utf-32le", "\x04\x03\x00\x00");
|
||||
success("utf-32le", "\x04\x03\x00\x00", "utf-32be", "\x00\x00\x03\x04");
|
||||
success("utf-32be", "\x00\x00\xFF\xFF", "utf-16be", "\xFF\xFF");
|
||||
success("utf-16be", "\xFF\xFF", "utf-32be", "\x00\x00\xFF\xFF");
|
||||
success("utf-32be", "\x00\x01\x00\x00", "utf-16be", "\xD8\x00\xDC\x00");
|
||||
success("utf-16be", "\xD8\x00\xDC\x00", "utf-32be", "\x00\x01\x00\x00");
|
||||
success("utf-32be", "\x00\x10\xFF\xFF", "utf-16be", "\xDB\xFF\xDF\xFF");
|
||||
success("utf-16be", "\xDB\xFF\xDF\xFF", "utf-32be", "\x00\x10\xFF\xFF");
|
||||
eilseq("utf-32be", "\x00\x11\x00\x00", "utf-16be", "");
|
||||
eilseq("utf-16be", "\xDB\xFF\xE0\x00", "utf-32be", "");
|
||||
success("utf-8", "\xE3\x81\x82", "utf-16be", "\x30\x42");
|
||||
einval("utf-8", "\xE3", "utf-16be", "");
|
||||
}
|
||||
|
||||
/* Japanese (CP932 CP20932 CP50220 CP50221 CP50222 CP51932) */
|
||||
if (check_enc("cp932", 932)
|
||||
&& check_enc("cp20932", 20932) && check_enc("euc-jp", 51932)
|
||||
&& check_enc("cp50220", 50220) && check_enc("cp50221", 50221)
|
||||
&& check_enc("cp50222", 50222) && check_enc("iso-2022-jp", 50221))
|
||||
{
|
||||
/* Test the compatibility for each other Japanese codepage.
|
||||
* And validate the escape sequence handling for iso-2022-jp. */
|
||||
success("utf-16be", "\xFF\x5E", "cp932", "\x81\x60");
|
||||
success("utf-16be", "\x30\x1C", "cp932", "\x81\x60");
|
||||
success("utf-16be", "\xFF\x5E", "cp932//nocompat", "\x81\x60");
|
||||
eilseq("utf-16be", "\x30\x1C", "cp932//nocompat", "");
|
||||
success("euc-jp", "\xA4\xA2", "utf-16be", "\x30\x42");
|
||||
einval("euc-jp", "\xA4\xA2\xA4", "utf-16be", "\x30\x42");
|
||||
eilseq("euc-jp", "\xA4\xA2\xFF\xFF", "utf-16be", "\x30\x42");
|
||||
success("cp932", "\x81\x60", "iso-2022-jp", "\x1B\x24\x42\x21\x41\x1B\x28\x42");
|
||||
success("UTF-16BE", "\xFF\x5E", "iso-2022-jp", "\x1B\x24\x42\x21\x41\x1B\x28\x42");
|
||||
eilseq("UTF-16BE", "\x30\x1C", "iso-2022-jp//nocompat", "");
|
||||
success("UTF-16BE", "\x30\x42\x30\x44", "iso-2022-jp", "\x1B\x24\x42\x24\x22\x24\x24\x1B\x28\x42");
|
||||
success("iso-2022-jp", "\x1B\x24\x42\x21\x41\x1B\x28\x42", "UTF-16BE", "\xFF\x5E");
|
||||
}
|
||||
|
||||
/*
|
||||
* test for //translit
|
||||
* U+FF41 (FULLWIDTH LATIN SMALL LETTER A) <-> U+0062 (LATIN SMALL LETTER A)
|
||||
*/
|
||||
eilseq("UTF-16BE", "\xFF\x41", "iso-8859-1", "");
|
||||
success("UTF-16BE", "\xFF\x41", "iso-8859-1//translit", "a");
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* Test for state after iconv() failed.
|
||||
* Ensure iconv() error is safe and continuable.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue