luat_lib_iconv.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. @module iconv
  3. @summary iconv操作
  4. @catalog 外设API
  5. @version 1.0
  6. @date 2023.03.03
  7. @demo iconv
  8. @tag LUAT_USE_ICONV
  9. */
  10. /*
  11. * luaiconv - Performs character set conversions in Lua
  12. * (c) 2005-08 Alexandre Erwin Ittner <aittner@gmail.com>
  13. *
  14. * Permission is hereby granted, free of charge, to any person obtaining
  15. * a copy of this software and associated documentation files (the
  16. * "Software"), to deal in the Software without restriction, including
  17. * without limitation the rights to use, copy, modify, merge, publish,
  18. * distribute, sublicense, and/or sell copies of the Software, and to
  19. * permit persons to whom the Software is furnished to do so, subject to
  20. * the following conditions:
  21. *
  22. * The above copyright notice and this permission notice shall be
  23. * included in all copies or substantial portions of the Software.
  24. *
  25. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  26. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  27. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  28. * IN NO EVENT SHALL THE AUTHOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY
  29. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  30. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  31. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  32. *
  33. * If you use this package in a product, an acknowledgment in the product
  34. * documentation would be greatly appreciated (but it is not required).
  35. *
  36. * $Id: luaiconv.c 54 2008-05-19 00:37:56Z dermeister $
  37. *
  38. */
  39. #include "lua.h"
  40. #include "lauxlib.h"
  41. #include <stdlib.h>
  42. #include "luat_base.h"
  43. #include "luat_mem.h"
  44. #define LIB_NAME "iconv"
  45. #define LIB_VERSION LIB_NAME " r5"
  46. #define ICONV_TYPENAME "iconv_t"
  47. #define LUAT_LOG_TAG "iconv"
  48. #include "luat_log.h"
  49. /* Emulates lua_(un)boxpointer from Lua 5.0 (don't exists on Lua 5.1) */
  50. #define boxptr(L, p) (*(void**)(lua_newuserdata(L, sizeof(void*))) = (p))
  51. #define unboxptr(L, i) (*(void**)(lua_touserdata(L, i)))
  52. /* Table assumed on top */
  53. #define tblseticons(L, c, v) \
  54. lua_pushliteral(L, c); \
  55. lua_pushnumber(L, v); \
  56. lua_settable(L, -3);
  57. #define ERROR_NO_MEMORY 1
  58. #define ERROR_INVALID 2
  59. #define ERROR_INCOMPLETE 3
  60. #define ERROR_UNKNOWN 4
  61. #if 1
  62. #include "iconv.h"
  63. static void push_iconv_t(lua_State *L, iconv_t cd) {
  64. boxptr(L, cd);
  65. luaL_getmetatable(L, ICONV_TYPENAME);
  66. lua_setmetatable(L, -2);
  67. }
  68. static iconv_t get_iconv_t(lua_State *L, int i) {
  69. if (luaL_checkudata(L, i, ICONV_TYPENAME) != NULL) {
  70. iconv_t cd = unboxptr(L, i);
  71. if (cd == (iconv_t) NULL)
  72. luaL_error(L, "attempt to use an invalid " ICONV_TYPENAME);
  73. return cd;
  74. }
  75. luaL_argerror(L, i, "type not match");
  76. return NULL;
  77. }
  78. /*
  79. 打开相应字符编码转换函数
  80. @api iconv.open(tocode, fromcode)
  81. @string 释义:目标编码格式<br>取值:gb2312/ucs2/ucs2be/utf8
  82. @string 释义:源编码格式<br>取值:gb2312/ucs2/ucs2be/utf8
  83. @return userdata 编码转换函数的转换句柄,若不存在会返回nil
  84. @usage
  85. --unicode大端编码 转化为 utf8编码
  86. local ic = iconv.open("utf8", "ucs2be")
  87. */
  88. static int Liconv_open(lua_State *L) {
  89. const char *tocode = luaL_checkstring(L, 1);
  90. const char *fromcode = luaL_checkstring(L, 2);
  91. iconv_t cd = iconv_open(tocode, fromcode);
  92. if (cd != (iconv_t)(-1)) {
  93. push_iconv_t(L, cd); /* ok */
  94. return 1;
  95. }
  96. return 0;
  97. }
  98. /*
  99. 字符编码转换
  100. @api ic:iconv(inbuf)
  101. @string 释义:待转换字符串
  102. @return number 释义:返回编码转换后的结果<br>取值:0成功,-1失败
  103. @usage
  104. --unicode大端编码 转化为 utf8编码
  105. function ucs2beToUtf8(ucs2s)
  106. local ic = iconv.open("utf8", "ucs2be")
  107. return ic:iconv(ucs2s)
  108. end
  109. */
  110. static int Liconv(lua_State *L) {
  111. iconv_t cd = get_iconv_t(L, 1);
  112. size_t ibleft = 0;
  113. char *inbuf = (char*) luaL_checklstring(L, 2, &ibleft);
  114. char *outbuf;
  115. char *outbufs;
  116. size_t obsize = ibleft * 2.1;
  117. size_t obleft = obsize;
  118. size_t ret = 0;
  119. outbuf = (char*) luat_heap_malloc(obsize * sizeof(char));
  120. if (outbuf == NULL) {
  121. lua_pushstring(L, "");
  122. lua_pushnumber(L, ERROR_NO_MEMORY);
  123. return 2;
  124. }
  125. outbufs = outbuf;
  126. // LLOGD("转换前的各种参数 ibleft %d obleft %d", ibleft, obleft);
  127. ret = iconv_convert(cd, &inbuf, &ibleft, &outbuf, &obleft);
  128. // LLOGD("转换后的各种参数 ibleft %d obleft %d", ibleft, obleft);
  129. if (ret == 0) {
  130. lua_pushlstring(L, outbufs, obsize - obleft);
  131. }
  132. else {
  133. lua_pushstring(L, "");
  134. }
  135. luat_heap_free(outbufs);
  136. return 1; /* Done */
  137. }
  138. #ifdef HAS_ICONVLIST /* a GNU extension? */
  139. static int push_one(unsigned int cnt, char *names[], void *data) {
  140. lua_State *L = (lua_State*) data;
  141. int n = (int) lua_tonumber(L, -1);
  142. int i;
  143. /* Stack: <tbl> n */
  144. lua_remove(L, -1);
  145. for (i = 0; i < cnt; i++) {
  146. /* Stack> <tbl> */
  147. lua_pushnumber(L, n++);
  148. lua_pushstring(L, names[i]);
  149. /* Stack: <tbl> n <str> */
  150. lua_settable(L, -3);
  151. }
  152. lua_pushnumber(L, n);
  153. /* Stack: <tbl> n */
  154. return 0;
  155. }
  156. static int Liconvlist(lua_State *L) {
  157. lua_newtable(L);
  158. lua_pushnumber(L, 1);
  159. /* Stack: <tbl> 1 */
  160. iconvlist(push_one, (void*) L);
  161. /* Stack: <tbl> n */
  162. lua_remove(L, -1);
  163. return 1;
  164. }
  165. #endif
  166. /*
  167. 关闭字符编码转换
  168. @api iconv.close(cd)
  169. @userdata iconv.open返回的句柄
  170. @return bool 成功返回true,否则返回false
  171. @usage
  172. --关闭字符编码转换
  173. local cd = iconv.open("utf8", "ucs2be")
  174. iconv.close(cd)
  175. */
  176. static int Liconv_close(lua_State *L) {
  177. iconv_t cd = get_iconv_t(L, 1);
  178. if (iconv_close(cd) == 0)
  179. lua_pushboolean(L, 1); /* ok */
  180. else
  181. lua_pushnil(L); /* erro */
  182. return 1;
  183. }
  184. // #include "rotable.h"
  185. #include "rotable2.h"
  186. static const rotable_Reg_t inconvFuncs[] = {
  187. { "open", ROREG_FUNC(Liconv_open)},
  188. { "new", ROREG_FUNC(Liconv_open)},
  189. { "iconv", ROREG_FUNC(Liconv)},
  190. #ifdef HAS_ICONVLIST
  191. { "list", ROREG_FUNC(Liconvlist)},
  192. #endif
  193. { "ERROR_NO_MEMORY", ROREG_INT(ERROR_NO_MEMORY)},
  194. { "ERROR_INVALID", ROREG_INT(ERROR_INVALID)},
  195. { "ERROR_INCOMPLETE", ROREG_INT(ERROR_INCOMPLETE)},
  196. { "ERROR_UNKNOWN", ROREG_INT(ERROR_UNKNOWN)},
  197. { NULL, ROREG_INT(0)}
  198. };
  199. // static const rotable_Reg iconvMT[] = {
  200. // { "__gc", Liconv_close , 0},
  201. // { NULL, NULL, NULL}
  202. // };
  203. LUAMOD_API int luaopen_iconv(lua_State *L) {
  204. luat_newlib2(L, inconvFuncs);
  205. // luaL_newmetatable(L, ICONV_TYPENAME);
  206. // lua_pushliteral(L, "__index");
  207. // rotable_newidx(L, iconvMT);
  208. // lua_settable(L, -3);
  209. // lua_pop(L, 1);
  210. luaL_newmetatable(L, ICONV_TYPENAME);
  211. lua_pushliteral(L, "__index");
  212. lua_pushvalue(L, -3);
  213. lua_settable(L, -3);
  214. lua_pushliteral(L, "__gc");
  215. lua_pushcfunction(L, Liconv_close);
  216. lua_settable(L, -3);
  217. lua_pop(L, 1);
  218. return 1;
  219. }
  220. #else
  221. #include "rotable.h"
  222. static const rotable_Reg iconvMT[] = {
  223. { NULL, NULL, NULL}
  224. };
  225. #endif