[PATCH] Add wrapper for platform-specific libiconv

Konstantin Belyavskiy k.belyavskiy at tarantool.org
Tue Feb 20 19:58:12 MSK 2018


On FREEBSD we have either system iconv lib or the one in /usr/local
Both hide real function name so specific include file is required.
But it doesn't work with Lua FFI mechanism, so wrapper is an option
to solve this issue.

Under OSX link with icovn (or -liconv) is required
Under FreeBSD it depends, for /usr/local version also required.
TODO: add FindICONV.cmake (add correct include/ library)

Close #3073
---
 branch: gh-3073-iconv-wrapper
 extra/exports        |  3 +++
 src/CMakeLists.txt   |  8 ++++++++
 src/lua/iconv.lua    | 16 ++++++++--------
 src/lua/iconv_wrap.c | 23 ++++++++++++++++++++++
 src/lua/iconv_wrap.h | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 96 insertions(+), 8 deletions(-)
 create mode 100644 src/lua/iconv_wrap.c
 create mode 100644 src/lua/iconv_wrap.h

diff --git a/extra/exports b/extra/exports
index b4a89c23d..faa7882ec 100644
--- a/extra/exports
+++ b/extra/exports
@@ -38,6 +38,9 @@ title_set_custom
 title_get_custom
 title_set_status
 title_get_status
+iconv_wrap_open
+iconv_wrap_close
+iconv_wrap
 exception_get_string
 exception_get_int
 
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e5acef738..a337c9d00 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -158,6 +158,7 @@ set (server_sources
      lua/msgpack.c
      lua/utils.c
      lua/errno.c
+     lua/iconv_wrap.c
      lua/socket.c
      lua/pickle.c
      lua/fio.c
@@ -214,12 +215,19 @@ target_link_libraries(server core bit uri uuid)
 set (reexport_libraries server core misc bitset csv
      ${LUAJIT_LIBRARIES} ${MSGPUCK_LIBRARIES} ${ICU_LIBRARIES})
 
+if (TARGET_OS_DARWIN)
+    set (ICONV_LIBRARIES /usr/lib/libiconv.dylib)
+elseif (TARGET_OS_FREEBSD)
+    set (ICONV_LIBRARIES /usr/local/lib/libiconv.so)
+endif()
+
 set (common_libraries
     ${reexport_libraries}
     ${LIBYAML_LIBRARIES}
     ${READLINE_LIBRARIES}
     ${OPENSSL_LIBRARIES}
     ${CURL_LIBRARIES}
+    ${ICONV_LIBRARIES}
 )
 
 if (TARGET_OS_LINUX OR TARGET_OS_DEBIAN_FREEBSD)
diff --git a/src/lua/iconv.lua b/src/lua/iconv.lua
index 304768d8f..08ad310c3 100644
--- a/src/lua/iconv.lua
+++ b/src/lua/iconv.lua
@@ -4,9 +4,9 @@ local buffer = require('buffer')
 
 ffi.cdef[[
 typedef struct iconv *iconv_t;
-iconv_t iconv_open(const char *tocode, const char *fromcode);
-void    iconv_close(iconv_t cd);
-size_t  iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft,
+iconv_t iconv_wrap_open(const char *tocode, const char *fromcode);
+void    iconv_wrap_close(iconv_t cd);
+size_t  iconv_wrap(iconv_t cd, const char **inbuf, size_t *inbytesleft,
               char **outbuf, size_t *outbytesleft);
 ]]
 
@@ -41,10 +41,10 @@ local function iconv_convert(iconv, data)
     while data_left[0] > 0 do
         buf_ptr[0]  = buf:reserve(output_len)
         buf_left[0] = buf:unused()
-        local res = ffi.C.iconv(iconv, data_ptr, data_left,
+        local res = ffi.C.iconv_wrap(iconv, data_ptr, data_left,
                                 buf_ptr, buf_left)
         if res == ffi.cast('size_t', -1) and errno() ~= E2BIG then
-            ffi.C.iconv(iconv, nil, nil, nil, nil)
+            ffi.C.iconv_wrap(iconv, nil, nil, nil, nil)
             if errno() == EINVAL then
                 error('Invalid multibyte sequence')
             end
@@ -57,7 +57,7 @@ local function iconv_convert(iconv, data)
     end
 
     -- iconv function sets cd's conversion state to the initial state
-    ffi.C.iconv(iconv, nil, nil, nil, nil)
+    ffi.C.iconv_wrap(iconv, nil, nil, nil, nil)
     local result = ffi.string(buf.rpos, buf:size())
     buf:reset()
     return result
@@ -65,7 +65,7 @@ end
 
 local iconv_mt = {
     __call = iconv_convert,
-    __gc = ffi.C.iconv_close,
+    __gc = ffi.C.iconv_wrap_close,
     __tostring = function(iconv) return string.format("iconv: %p", iconv) end
 }
 
@@ -75,7 +75,7 @@ local function iconv_new(to, from)
     if type(to) ~= 'string' or type(from) ~= 'string' then
         error('Usage: iconv.new("CP1251", "KOI8-R")')
     end
-    local iconv = ffi.C.iconv_open(to, from)
+    local iconv = ffi.C.iconv_wrap_open(to, from)
     if iconv == conv_rv_error then
         error('iconv: '..errno.strerror())
     end
diff --git a/src/lua/iconv_wrap.c b/src/lua/iconv_wrap.c
new file mode 100644
index 000000000..2cf6be883
--- /dev/null
+++ b/src/lua/iconv_wrap.c
@@ -0,0 +1,23 @@
+#include <iconv.h>
+#include "iconv_wrap.h"
+
+iconv_t
+iconv_wrap_open(const char *tocode, const char *fromcode)
+{
+        return iconv_open(tocode, fromcode);
+}
+
+int
+iconv_wrap_close(iconv_t cd)
+{
+        return iconv_close(cd);
+}
+
+size_t
+iconv_wrap(iconv_t cd,
+           char **inbuf, size_t *inbytesleft,
+           char **outbuf, size_t *outbytesleft)
+{
+        return iconv(cd, inbuf, inbytesleft,
+                     outbuf, outbytesleft);
+}
diff --git a/src/lua/iconv_wrap.h b/src/lua/iconv_wrap.h
new file mode 100644
index 000000000..03aee40e4
--- /dev/null
+++ b/src/lua/iconv_wrap.h
@@ -0,0 +1,54 @@
+#ifndef TARANTOOL_LUA_ICONV_H_INCLUDED
+#define TARANTOOL_LUA_ICONV_H_INCLUDED
+/*
+ * Copyright 2010-2015, Tarantool AUTHORS, please see AUTHORS file.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
+struct iconv_t;
+
+iconv_t
+iconv_wrap_open(const char *tocode, const char *fromcode);
+
+int
+iconv_wrap_close(iconv_t cd);
+
+size_t
+iconv_wrap(iconv_t cd,
+           char **inbuf, size_t *inbytesleft,
+           char **outbuf, size_t *outbytesleft);
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
+#endif /* TARANTOOL_LUA_ICONV_H_INCLUDED */
-- 
2.14.3 (Apple Git-98)




More information about the Tarantool-patches mailing list