📄 converter.c
字号:
}idn_result_tidn_converter_aliasfile(const char *path) { idn_result_t r; assert(path != NULL); TRACE(("idn_converter_aliasfile(path=%s)\n", path)); if (encoding_alias_list == NULL) { WARNING(("idn_converter_aliasfile(): the module is not " "initialized\n")); return (idn_failure); } r = idn__aliaslist_aliasfile(encoding_alias_list, path); TRACE(("idn_converter_aliasfile(): %s\n", idn_result_tostring(r))); return (r);}idn_result_tidn_converter_resetalias(void) { idn__aliaslist_t list; idn_result_t r; TRACE(("idn_converter_resetalias()\n")); if (encoding_alias_list == NULL) { WARNING(("idn_converter_resetalias(): the module is not " "initialized\n")); return (idn_failure); } list = encoding_alias_list; encoding_alias_list = NULL; idn__aliaslist_destroy(list); list = NULL; r = idn__aliaslist_create(&list); encoding_alias_list = list; TRACE(("idn_converter_resetalias(): %s\n", idn_result_tostring(r))); return (r);}const char *idn_converter_getrealname(const char *name) { char *realname; idn_result_t r; TRACE(("idn_converter_getrealname()\n")); assert(name != NULL); if (encoding_alias_list == NULL) { WARNING(("idn_converter_getrealname(): the module is not " "initialized\n")); return (name); } r = idn__aliaslist_find(encoding_alias_list, name, &realname); if (r != idn_success) { return (name); } return (realname);}/* * Round trip check. */static idn_result_troundtrip_check(idn_converter_t ctx, const unsigned long *from, const char *to){ /* * One problem with iconv() convertion is that * iconv() doesn't signal an error if the input * string contains characters which are valid but * do not have mapping to the output codeset. * (the behavior of iconv() for that case is defined as * `implementation dependent') * One way to check this case is to perform round-trip * conversion and see if it is same as the original string. */ idn_result_t r; unsigned long *back; unsigned long backbuf[256]; size_t fromlen; size_t backlen; TRACE(("idn_converter_convert: round-trip checking (from=\"%s\")\n", idn__debug_ucs4xstring(from, 50))); /* Allocate enough buffer. */ fromlen = idn_ucs4_strlen(from) + 1; if (fromlen * sizeof(*back) <= sizeof(backbuf)) { backlen = sizeof(backbuf); back = backbuf; } else { backlen = fromlen; back = (unsigned long *)malloc(backlen * sizeof(*back)); if (back == NULL) return (idn_nomemory); } /* * Perform backward conversion. */ r = idn_converter_convtoucs4(ctx, to, back, backlen); switch (r) { case idn_success: if (memcmp(back, from, sizeof(*from) * fromlen) != 0) r = idn_nomapping; break; case idn_invalid_encoding: case idn_buffer_overflow: r = idn_nomapping; break; default: break; } if (back != backbuf) free(back); if (r != idn_success) { TRACE(("round-trip check failed: %s\n", idn_result_tostring(r))); } return (r);}/* * Identity conversion (or, no conversion at all). */static idn_result_tconverter_none_open(idn_converter_t ctx, void **privdata) { assert(ctx != NULL); return (idn_success);}static idn_result_tconverter_none_close(idn_converter_t ctx, void *privdata) { assert(ctx != NULL); return (idn_success);}static idn_result_tconverter_none_convfromucs4(idn_converter_t ctx, void *privdata, const unsigned long *from, char *to, size_t tolen) { assert(ctx != NULL && from != NULL && to != NULL); return idn_ucs4_ucs4toutf8(from, to, tolen);}static idn_result_tconverter_none_convtoucs4(idn_converter_t ctx, void *privdata, const char *from, unsigned long *to, size_t tolen) { assert(ctx != NULL && from != NULL && to != NULL); return idn_ucs4_utf8toucs4(from, to, tolen);}#ifndef WITHOUT_ICONV/* * Conversion using iconv() interface. */static idn_result_tconverter_iconv_openfromucs4(idn_converter_t ctx, void **privdata) { iconv_t *ictxp; idn_result_t r; assert(ctx != NULL); r = iconv_initialize_privdata(privdata); if (r != idn_success) return (r); ictxp = (iconv_t *)*privdata; *ictxp = iconv_open(ctx->local_encoding_name, IDN_UTF8_ENCODING_NAME); if (*ictxp == (iconv_t)(-1)) { free(*privdata); *privdata = NULL; switch (errno) { case ENOMEM: return (idn_nomemory); case EINVAL: return (idn_invalid_name); default: WARNING(("iconv_open failed with errno %d\n", errno)); return (idn_failure); } } return (idn_success);}static idn_result_tconverter_iconv_opentoucs4(idn_converter_t ctx, void **privdata) { iconv_t *ictxp; idn_result_t r; assert(ctx != NULL); r = iconv_initialize_privdata(privdata); if (r != idn_success) return (r); ictxp = (iconv_t *)*privdata + 1; *ictxp = iconv_open(IDN_UTF8_ENCODING_NAME, ctx->local_encoding_name); if (*ictxp == (iconv_t)(-1)) { free(*privdata); *privdata = NULL; switch (errno) { case ENOMEM: return (idn_nomemory); case EINVAL: return (idn_invalid_name); default: WARNING(("iconv_open failed with errno %d\n", errno)); return (idn_failure); } } return (idn_success);}static idn_result_ticonv_initialize_privdata(void **privdata) { if (*privdata == NULL) { *privdata = malloc(sizeof(iconv_t) * 2); if (*privdata == NULL) return (idn_nomemory); *((iconv_t *)*privdata) = (iconv_t)(-1); *((iconv_t *)*privdata + 1) = (iconv_t)(-1); } return (idn_success);}static voidiconv_finalize_privdata(void *privdata) { iconv_t *ictxp; if (privdata != NULL) { ictxp = (iconv_t *)privdata; if (*ictxp != (iconv_t)(-1)) iconv_close(*ictxp); ictxp++; if (*ictxp != (iconv_t)(-1)) iconv_close(*ictxp); free(privdata); }}static idn_result_tconverter_iconv_close(idn_converter_t ctx, void *privdata) { assert(ctx != NULL); iconv_finalize_privdata(privdata); return (idn_success);}static idn_result_tconverter_iconv_convfromucs4(idn_converter_t ctx, void *privdata, const unsigned long *from, char *to, size_t tolen) { iconv_t ictx; char *utf8 = NULL; size_t utf8size = 256; /* large enough */ idn_result_t r; size_t sz; size_t inleft; size_t outleft; char *inbuf, *outbuf; assert(ctx != NULL && from != NULL && to != NULL); if (tolen <= 0) { r = idn_buffer_overflow; /* need space for NUL */ goto ret; } /* * UCS4 -> UTF-8 conversion. */ utf8 = (char *)malloc(utf8size); if (utf8 == NULL) { r = idn_nomemory; goto ret; }try_again: r = idn_ucs4_ucs4toutf8(from, utf8, utf8size); if (r == idn_buffer_overflow) { char *new_utf8; utf8size *= 2; new_utf8 = (char *)realloc(utf8, utf8size); if (new_utf8 == NULL) { r = idn_nomemory; goto ret; } utf8 = new_utf8; goto try_again; } else if (r != idn_success) { goto ret; } ictx = ((iconv_t *)privdata)[0]; /* * Reset internal state. * * The following code should work according to the SUSv2 spec, * but causes segmentation fault with Solaris 2.6. * So.. a work-around. * * (void)iconv(ictx, (const char **)NULL, (size_t *)NULL, * (char **)NULL, (size_t *)NULL); */ inleft = 0; outbuf = NULL; outleft = 0; (void)iconv(ictx, (const char **)NULL, &inleft, &outbuf, &outleft); inleft = strlen(utf8); inbuf = utf8; outleft = tolen - 1; /* reserve space for terminating NUL */ sz = iconv(ictx, (const char **)&inbuf, &inleft, &to, &outleft); if (sz == (size_t)(-1) || inleft > 0) { switch (errno) { case EILSEQ: case EINVAL: /* * We already checked the validity of the input * string. So we assume a mapping error. */ r = idn_nomapping; goto ret; case E2BIG: r = idn_buffer_overflow; goto ret; default: WARNING(("iconv failed with errno %d\n", errno)); r = idn_failure; goto ret; } } /* * For UTF-8 -> local conversion, append a sequence of * state reset. */ inleft = 0; sz = iconv(ictx, (const char **)NULL, &inleft, &to, &outleft); if (sz == (size_t)(-1)) { switch (errno) { case EILSEQ: case EINVAL: r = idn_invalid_encoding; goto ret; case E2BIG: r = idn_buffer_overflow; goto ret; default: WARNING(("iconv failed with errno %d\n", errno)); r = idn_failure; goto ret; } } *to = '\0'; r = idn_success;ret: free(utf8); return (r);}static idn_result_tconverter_iconv_convtoucs4(idn_converter_t ctx, void *privdata, const char *from, unsigned long *to, size_t tolen) { iconv_t ictx; char *utf8 = NULL; size_t utf8size = 256; /* large enough */ idn_result_t r; size_t sz; size_t inleft; size_t outleft; const char *from_ptr; char *outbuf; assert(ctx != NULL && from != NULL && to != NULL); if (tolen <= 0) { r = idn_buffer_overflow; /* need space for NUL */ goto ret; } ictx = ((iconv_t *)privdata)[1]; utf8 = (char *)malloc(utf8size); if (utf8 == NULL) { r = idn_nomemory; goto ret; }try_again: /* * Reset internal state. */ inleft = 0; outbuf = NULL; outleft = 0; (void)iconv(ictx, (const char **)NULL, &inleft, &outbuf, &outleft); from_ptr = from; inleft = strlen(from); outbuf = utf8; outleft = utf8size - 1; /* reserve space for terminating NUL */ sz = iconv(ictx, (const char **)&from_ptr, &inleft, &outbuf, &outleft); if (sz == (size_t)(-1) || inleft > 0) { char *new_utf8; switch (errno) { case EILSEQ: case EINVAL: /* * We assume all the characters in the local * codeset are included in UCS. This means mapping * error is not possible, so the input string must * have some problem. */ r = idn_invalid_encoding; goto ret; case E2BIG: utf8size *= 2; new_utf8 = (char *)realloc(utf8, utf8size); if (new_utf8 == NULL) { r = idn_nomemory; goto ret; } utf8 = new_utf8; goto try_again; default: WARNING(("iconv failed with errno %d\n", errno)); r = idn_failure; goto ret; } } *outbuf = '\0'; /* * UTF-8 -> UCS4 conversion. */ r = idn_ucs4_utf8toucs4(utf8, to, tolen);ret: free(utf8); return (r);}#endif /* !WITHOUT_ICONV */#ifdef DEBUG/* * Conversion to/from unicode escape string. * Arbitrary UCS-4 character can be specified by a special sequence * \u{XXXXXX} * where XXXXX denotes any hexadecimal string up to FFFFFFFF. * This is designed for debugging. */static idn_result_tconverter_uescape_convfromucs4(idn_converter_t ctx, void *privdata, const unsigned long *from, char *to, size_t tolen) { idn_result_t r; unsigned long v; while (*from != '\0') { v = *from++; if (v <= 0x7f) { if (tolen < 1) { r = idn_buffer_overflow; goto failure; } *to++ = v; tolen--; } else if (v <= 0xffffffff) { char tmp[20]; int len; (void)sprintf(tmp, "\\u{%lx}", v); len = strlen(tmp); if (tolen < len) { r = idn_buffer_overflow; goto failure; } (void)memcpy(to, tmp, len); to += len; tolen -= len; } else { r = idn_invalid_encoding; goto failure; } } if (tolen <= 0) { r = idn_buffer_overflow; goto failure; } *to = '\0'; return (idn_success);failure: if (r != idn_buffer_overflow) { WARNING(("idn_uescape_convfromucs4(): %s\n", idn_result_tostring(r))); } return (r);}static idn_result_tconverter_uescape_convtoucs4(idn_converter_t ctx, void *privdata, const char *from, unsigned long *to, size_t tolen){ idn_result_t r; size_t fromlen = strlen(from); while (*from != '\0') { if (tolen <= 0) { r = idn_buffer_overflow; goto failure; } if (strncmp(from, "\\u{", 3) == 0 || strncmp(from, "\\U{", 3) == 0) { size_t ullen; unsigned long v; char *end; v = strtoul(from + 3, &end, 16); ullen = end - (from + 3); if (*end == '}' && ullen > 1 && ullen < 8) { *to = v; from = end + 1; fromlen -= ullen; } else { *to = '\\'; from++; fromlen--; } } else { int c = *(unsigned char *)from; size_t width; char buf[8]; if (c < 0x80) width = 1; else if (c < 0xc0) width = 0; else if (c < 0xe0) width = 2; else if (c < 0xf0) width = 3; else if (c < 0xf8) width = 4; else if (c < 0xfc) width = 5; else if (c < 0xfe) width = 6; else width = 0; if (width == 0 || width > fromlen) { r = idn_invalid_encoding; goto failure; } memcpy(buf, from, width); buf[width] = '\0'; r = idn_ucs4_utf8toucs4(buf, to, tolen); if (r != idn_success) { r = idn_invalid_encoding; goto failure; } from += width; fromlen -= width; } to++; tolen--; } if (tolen <= 0) { r = idn_buffer_overflow; goto failure; } *to = '\0'; return (idn_success);failure: if (r != idn_buffer_overflow) { WARNING(("idn_uescape_convtoucs4(): %s\n", idn_result_tostring(r))); } return (r);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -