static int luacconv(lua_State *L) { cconv_t cd; const char *fromcode, *tocode, *str; char *outstr, *p; size_t inlen, outlen, size; if (lua_gettop(L) != 3) { lua_pushstring(L, "Bad argument number"); lua_error(L); return 1; } fromcode = lua_tostring(L, 1); tocode = lua_tostring(L, 2); str = lua_tolstring(L, 3, &inlen); if((cd = cconv_open(tocode, fromcode)) == (cconv_t)(-1)) { lua_pushstring(L, str); return 1; } outlen = 3 * inlen; outstr = p = (char *)malloc(outlen); cm_memzero(outstr, outlen); size = cconv(cd, (const char **)&str, &inlen, &p, &outlen); cconv_close(cd); if (size == (size_t)(-1)) { lua_pushstring(L, str); free(outstr); return 1; } lua_pushstring(L, outstr); free(outstr); return 1; }
/** * Open a cconv handle. * * @param tocode Convert to-code. * @param fromcode Convert from-code. * @retval t_handle Cconv handle,(-1: error). */ cconv_t cconv_open(const char* tocode, const char* fromcode) { char code[8] = {0, }; char *ptr; cconv_struct* cd = (cconv_struct*)malloc(sizeof(cconv_struct)); cd->cconv_cd = CCONV_NULL; cd->iconv_cd = NULL; cd->gb_utf8 = NULL; cd->bg_utf8 = NULL; cd->utf8_gb = NULL; cd->utf8_bg = NULL; cd->size_factor = 4; /* //IGNORE //TRANSPORT etc. */ if((ptr = strstr(fromcode, "//")) != NULL) { strncpy(cd->options, ptr , 16); strncpy(code , fromcode, ptr - fromcode); fromcode = code; } if(0 == strcasecmp(CCONV_CODE_GBL, fromcode)) { cd->gb_utf8 = iconv_open(CCONV_CODE_UTF, CCONV_CODE_GBL); if(0 == strcasecmp(CCONV_CODE_UHT, tocode) || 0 == strcasecmp(CCONV_CODE_UHK, tocode) ||0 == strcasecmp(CCONV_CODE_UTW, tocode)) { cd->cconv_cd = CCONV_GBL_TO_UHT; } else if(0 == strcasecmp(CCONV_CODE_UHS, tocode) || 0 == strcasecmp(CCONV_CODE_UCN, tocode)) cd->cconv_cd = CCONV_GBL_TO_UHS; else if(0 == strcasecmp(CCONV_CODE_BIG, tocode)) { cd->cconv_cd = CCONV_GBL_TO_BIG; cd->utf8_bg = iconv_open(CCONV_CODE_BIG, CCONV_CODE_UTF); } else if(0 == strcasecmp(CCONV_CODE_GHS, tocode)) { cd->cconv_cd = CCONV_GBL_TO_GHS; cd->utf8_gb = iconv_open(CCONV_CODE_GBL, CCONV_CODE_UTF); } else if(0 == strcasecmp(CCONV_CODE_GHT, tocode)) { cd->cconv_cd = CCONV_GBL_TO_GHT; cd->utf8_gb = iconv_open(CCONV_CODE_GBL, CCONV_CODE_UTF); } } else if(0 == strcasecmp(CCONV_CODE_UTF, fromcode) ||0 == strcasecmp(CCONV_CODE_UHS, fromcode) ||0 == strcasecmp(CCONV_CODE_UHT, fromcode) ||0 == strcasecmp(CCONV_CODE_UCN, fromcode) ||0 == strcasecmp(CCONV_CODE_UHK, fromcode) ||0 == strcasecmp(CCONV_CODE_UTW, fromcode) ) { if(0 == strcasecmp(CCONV_CODE_UHS, tocode) || 0 == strcasecmp(CCONV_CODE_UCN, tocode)) cd->cconv_cd = CCONV_UTF_TO_UHS; else if(0 == strcasecmp(CCONV_CODE_UHT, tocode) || 0 == strcasecmp(CCONV_CODE_UHK, tocode) || 0 == strcasecmp(CCONV_CODE_UTW, tocode)) cd->cconv_cd = CCONV_UTF_TO_UHT; else if(0 == strcasecmp(CCONV_CODE_GBL, tocode)) { cd->cconv_cd = CCONV_UTF_TO_GBL; cd->utf8_gb = iconv_open(CCONV_CODE_GBL, CCONV_CODE_UTF); } else if(0 == strcasecmp(CCONV_CODE_BIG, tocode)) { cd->cconv_cd = CCONV_UTF_TO_BIG; cd->utf8_bg = iconv_open(CCONV_CODE_BIG, CCONV_CODE_UTF); } cd->size_factor = 1; } else if(0 == strcasecmp(CCONV_CODE_BIG, fromcode)) { if(0 == strcasecmp(CCONV_CODE_GBL, tocode)) { cd->cconv_cd = CCONV_BIG_TO_GBL; cd->bg_utf8 = iconv_open(CCONV_CODE_UTF, CCONV_CODE_BIG); cd->utf8_gb = iconv_open(CCONV_CODE_GBL, CCONV_CODE_UTF); } else if(0 == strcasecmp(CCONV_CODE_UHS, tocode) || 0 == strcasecmp(CCONV_CODE_UCN, tocode)) { cd->cconv_cd = CCONV_BIG_TO_UHS; cd->bg_utf8 = iconv_open(CCONV_CODE_UTF, CCONV_CODE_BIG); } /* just use iconv to do others. */ } if(cd->cconv_cd == CCONV_NULL) cd->iconv_cd = iconv_open(tocode, fromcode); if( cd->iconv_cd == (iconv_t)(-1) || cd->gb_utf8 == (iconv_t)(-1) || cd->bg_utf8 == (iconv_t)(-1) || cd->utf8_gb == (iconv_t)(-1) || cd->utf8_bg == (iconv_t)(-1)) { cconv_close(cd); return (cconv_t)(CCONV_ERROR); } return cd; }