From 97afe4fd6ad8b2b05d7e56d405aed5be745a272c Mon Sep 17 00:00:00 2001
From: Konstantin Osipov <kostja@tarantool.org>
Date: Sun, 2 Jun 2013 12:53:53 +0400
Subject: [PATCH] Add lua-cjson support in box.cjson

Code review of cjson branch by Dmitry E. Oboukhov.
Hand-picking the changes since the original branch
is based on import of lua-cjson into Tarantool
revision tree, and this branch is based on a git
submodule.

This patch implements
https://blueprints.launchpad.net/tarantool/+spec/lua-cjson
---
 CMakeLists.txt            |  8 +++++++
 cmake/BuildLibCJSON.cmake | 17 +++++++++++++++
 include/lua/cjson.h       | 38 ++++++++++++++++++++++++++++++++
 src/CMakeLists.txt        |  2 ++
 src/lua/cjson.m           | 46 +++++++++++++++++++++++++++++++++++++++
 src/lua/init.m            |  2 ++
 test/box/cjson.result     | 37 +++++++++++++++++++++++++++++++
 test/box/cjson.test       | 13 +++++++++++
 test/box/lua.result       |  4 ++--
 9 files changed, 165 insertions(+), 2 deletions(-)
 create mode 100644 cmake/BuildLibCJSON.cmake
 create mode 100644 include/lua/cjson.h
 create mode 100644 src/lua/cjson.m
 create mode 100644 test/box/cjson.result
 create mode 100644 test/box/cjson.test

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 072c8bd4cc..5a7284e10a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -327,6 +327,14 @@ include(BuildLibGOPT)
 libgopt_build()
 add_dependencies(build_bundled_libs gopt)
 
+#
+# LibCJSON
+#
+
+include(BuildLibCJSON)
+libcjson_build()
+add_dependencies(build_bundled_libs cjson)
+
 #
 # Third-Party misc
 #
diff --git a/cmake/BuildLibCJSON.cmake b/cmake/BuildLibCJSON.cmake
new file mode 100644
index 0000000000..2c09c878ee
--- /dev/null
+++ b/cmake/BuildLibCJSON.cmake
@@ -0,0 +1,17 @@
+#
+# A macro to build the bundled liblua-cjson
+macro(libcjson_build)
+    set(cjson_src ${PROJECT_SOURCE_DIR}/third_party/lua-cjson/lua_cjson.c 
+                  ${PROJECT_SOURCE_DIR}/third_party/lua-cjson/strbuf.c 
+                  ${PROJECT_SOURCE_DIR}/third_party/lua-cjson/fpconv.c)
+
+    add_library(cjson STATIC ${cjson_src})
+
+    set(LIBCJSON_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/third_party/lua-cjson)
+    set(LIBCJSON_LIBRARIES cjson)
+
+    message(STATUS "Use bundled Lua-CJSON library: ${LIBCJSON_LIBRARIES}")
+
+    unset(lua_cjson_src)
+endmacro(libcjson_build)
+
diff --git a/include/lua/cjson.h b/include/lua/cjson.h
new file mode 100644
index 0000000000..9df3d97ac4
--- /dev/null
+++ b/include/lua/cjson.h
@@ -0,0 +1,38 @@
+#ifndef TARANTOOL_LUA_CJSON_H_INCLUDED
+#define TARANTOOL_LUA_CJSON_H_INCLUDED
+/*
+ * 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.
+ */
+
+struct lua_State;
+/**
+* Initialize box.cjson system
+*/
+int tarantool_lua_cjson_init(struct lua_State *L);
+
+#endif /* TARANTOOL_LUA_CJSON_H_INCLUDED */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c15d59babb..8028d32837 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -105,6 +105,7 @@ set (common_sources
      lua/lua_ipc.m
      lua/lua_socket.m
      lua/session.m
+     lua/cjson.m
 )
 
 if (ENABLE_TRACE)
@@ -122,6 +123,7 @@ list(APPEND common_libraries
     ${LIBEIO_LIBRARIES}
     ${LIBCORO_LIBRARIES}
     ${LIBGOPT_LIBRARIES}
+    ${LIBCJSON_LIBRARIES}
     ${LUAJIT_LIB}
     ${LIBOBJC_LIBRARIES}
     misc
diff --git a/src/lua/cjson.m b/src/lua/cjson.m
new file mode 100644
index 0000000000..112768bc97
--- /dev/null
+++ b/src/lua/cjson.m
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+#include "lua/cjson.h"
+
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+
+int luaopen_cjson(lua_State *l);
+
+int
+tarantool_lua_cjson_init(struct lua_State *L)
+{
+	lua_getfield(L, LUA_GLOBALSINDEX, "box");
+	lua_pushstring(L, "cjson");
+	luaopen_cjson(L);
+	lua_settable(L, -3);
+	lua_pop(L, 1);
+	return 0;
+}
diff --git a/src/lua/init.m b/src/lua/init.m
index be88775846..0f39799f8c 100644
--- a/src/lua/init.m
+++ b/src/lua/init.m
@@ -50,6 +50,7 @@
 #include "lua/stat.h"
 #include "lua/uuid.h"
 #include "lua/session.h"
+#include "lua/cjson.h"
 
 #include <sys/time.h>
 #include <sys/types.h>
@@ -1111,6 +1112,7 @@ tarantool_lua_init()
 	lua_register(L, "pcall", lbox_pcall);
 	lua_register(L, "tonumber64", lbox_tonumber64);
 
+	tarantool_lua_cjson_init(L);
 	tarantool_lua_info_init(L);
 	tarantool_lua_slab_init(L);
 	tarantool_lua_stat_init(L);
diff --git a/test/box/cjson.result b/test/box/cjson.result
new file mode 100644
index 0000000000..7cd8fdeaf3
--- /dev/null
+++ b/test/box/cjson.result
@@ -0,0 +1,37 @@
+cjson tests
+lua type(box.cjson)
+---
+ - table
+...
+lua box.cjson.encode(123)
+---
+ - 123
+...
+lua box.cjson.encode({123})
+---
+ - [123]
+...
+lua box.cjson.encode({123, 234, 345})
+---
+ - [123,234,345]
+...
+lua box.cjson.encode({abc = 234, cde = 345})
+---
+ - {"cde":345,"abc":234}
+...
+lua box.cjson.encode({Метапеременная = { 'Метазначение' } })
+---
+ - {"Метапеременная":["Метазначение"]}
+...
+lua box.cjson.decode('123')
+---
+ - 123
+...
+lua box.cjson.decode('[123, "Кудыкины горы"]')[2]
+---
+ - Кудыкины горы
+...
+lua box.cjson.decode('{"test": "Результат"}').test
+---
+ - Результат
+...
diff --git a/test/box/cjson.test b/test/box/cjson.test
new file mode 100644
index 0000000000..c44d07cc13
--- /dev/null
+++ b/test/box/cjson.test
@@ -0,0 +1,13 @@
+# encoding: tarantool
+# 
+print("cjson tests")
+exec admin "lua type(box.cjson)"
+exec admin "lua box.cjson.encode(123)"
+exec admin "lua box.cjson.encode({123})"
+exec admin "lua box.cjson.encode({123, 234, 345})"
+exec admin "lua box.cjson.encode({abc = 234, cde = 345})"
+exec admin "lua box.cjson.encode({Метапеременная = { 'Метазначение' } })"
+
+exec admin "lua box.cjson.decode('123')"
+exec admin "lua box.cjson.decode('[123, \"Кудыкины горы\"]')[2]"
+exec admin "lua box.cjson.decode('{\"test\": \"Результат\"}').test"
diff --git a/test/box/lua.result b/test/box/lua.result
index c0b4c136ba..f3775446c2 100644
--- a/test/box/lua.result
+++ b/test/box/lua.result
@@ -1914,7 +1914,7 @@ lua function bug1075677() local range = {} table.insert(range, 1>0) return range
 ...
 call bug1075677()
 Found 1 tuple:
-['true�']
+[1702195828]
 lua bug1075677=nil
 ---
 ...
@@ -1924,5 +1924,5 @@ lua box.tuple.new(false)
 ...
 lua box.tuple.new({false})
 ---
- - 'false\x00': {}
+ - 'false': {}
 ...
-- 
GitLab