diff --git a/src/connector/odbc/tests/tconv.c b/src/connector/odbc/tests/tconv.c new file mode 100644 index 0000000000000000000000000000000000000000..f0a528cf9a94a3359fdb9b2aaf3983614a30e734 --- /dev/null +++ b/src/connector/odbc/tests/tconv.c @@ -0,0 +1,132 @@ +#include "../src/todbc_log.h" + +#ifdef _MSC_VER +#include +#include +#include "msvcIconv.h" +#else +#include +#endif + + +#include +#include + +static void usage(const char *arg0); +static int do_conv(iconv_t cnv, FILE *fin); + +int main(int argc, char *argv[]) { + const char *from_enc = "UTF-8"; + const char *to_enc = "UTF-8"; + const char *src = NULL; +#ifdef _MSC_VER + from_enc = "CP936"; + to_enc = "CP936"; +#endif + for (int i = 1; i < argc; i++) { + const char *arg = argv[i]; + if (strcmp(arg, "-h") == 0) { + usage(argv[0]); + return 0; + } else if (strcmp(arg, "-f") == 0 ) { + i += 1; + if (i>=argc) { + fprintf(stderr, "expecing , but got nothing\n"); + return 1; + } + from_enc = argv[i]; + continue; + } else if (strcmp(arg, "-t") == 0 ) { + i += 1; + if (i>=argc) { + fprintf(stderr, "expecing , but got nothing\n"); + return 1; + } + to_enc = argv[i]; + continue; + } else if (arg[0]=='-') { + fprintf(stderr, "unknown argument: [%s]\n", arg); + return 1; + } else { + if (src) { + fprintf(stderr, "does not allow multiple files\n"); + return 1; + } + src = arg; + continue; + } + } + FILE *fin = src ? fopen(src, "rb") : stdin; + if (!fin) { + fprintf(stderr, "failed to open file [%s]\n", src); + return 1; + } + int r = 0; + do { + iconv_t cnv = iconv_open(to_enc, from_enc); + if (cnv == (iconv_t)-1) { + fprintf(stderr, "failed to open conv from [%s] to [%s]: [%s]\n", from_enc, to_enc, strerror(errno)); + return -1; + } + r = do_conv(cnv, fin); + iconv_close(cnv); + } while (0); + fclose(fin); + return r ? 1 : 0; +} + +static void usage(const char *arg0) { + fprintf(stderr, "%s -h | [-f ] [-t ] [file]\n", arg0); + return; +} + +#define IN_SIZE (256*1024) +#define OUT_SIZE (8*IN_SIZE) +static int do_conv(iconv_t cnv, FILE *fin) { + int r = 0; + char src[IN_SIZE]; + size_t slen = sizeof(src); + char dst[OUT_SIZE]; + size_t dlen = sizeof(dst); + char *start = src; + while (!feof(fin)) { + slen = (size_t)(src + sizeof(src) - start); + size_t n = fread(start, 1, slen, fin); + if (n>0) { + char *ss = src; + size_t sl = n; + while (sl) { + char *dd = dst; + size_t dn = dlen; + size_t v = iconv(cnv, &ss, &sl, &dd, &dn); + if (v==(size_t)-1) { + int err = errno; + if (err == EILSEQ) { + fprintf(stderr, "failed to convert: [%s]\n", strerror(err)); + r = -1; + break; + } + if (err == EINVAL) { + fprintf(stderr, "[%s]\n", strerror(errno)); + size_t ava = (size_t)(src + sizeof(src) - ss); + memcpy(src, ss, ava); + start = ss; + } else { + fprintf(stderr, "internal logic error: [%s]\n", strerror(errno)); + r = -1; + break; + } + } + n = fwrite(dst, 1, (size_t)(dd-dst), stdout); + if (n