1 | /* |
2 | * Copyright 2008-2018 Aerospike, Inc. |
3 | * |
4 | * Portions may be licensed to Aerospike, Inc. under one or more contributor |
5 | * license agreements. |
6 | * |
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
8 | * use this file except in compliance with the License. You may obtain a copy of |
9 | * the License at http://www.apache.org/licenses/LICENSE-2.0 |
10 | * |
11 | * Unless required by applicable law or agreed to in writing, software |
12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
14 | * License for the specific language governing permissions and limitations under |
15 | * the License. |
16 | */ |
17 | |
18 | #include <lua.h> |
19 | #include <lauxlib.h> |
20 | #include <lualib.h> |
21 | |
22 | #include <aerospike/as_val.h> |
23 | |
24 | #include <aerospike/mod_lua_val.h> |
25 | #include <aerospike/mod_lua_stream.h> |
26 | #include <aerospike/mod_lua_reg.h> |
27 | |
28 | #include "internal.h" |
29 | |
30 | |
31 | /******************************************************************************* |
32 | * MACROS |
33 | ******************************************************************************/ |
34 | |
35 | #define OBJECT_NAME "stream" |
36 | #define CLASS_NAME "Stream" |
37 | |
38 | /******************************************************************************* |
39 | * FUNCTIONS |
40 | ******************************************************************************/ |
41 | |
42 | as_stream * mod_lua_tostream(lua_State * l, int index) { |
43 | mod_lua_box * box = mod_lua_tobox(l, index, CLASS_NAME); |
44 | return (as_stream *) mod_lua_box_value(box); |
45 | } |
46 | |
47 | as_stream * mod_lua_pushstream(lua_State * l, as_stream * stream) { |
48 | mod_lua_box * box = mod_lua_pushbox(l, MOD_LUA_SCOPE_HOST, stream, CLASS_NAME); |
49 | return (as_stream *) mod_lua_box_value(box); |
50 | } |
51 | |
52 | // static as_stream * mod_lua_checkstream(lua_State * l, int index) { |
53 | // mod_lua_box * box = mod_lua_checkbox(l, index, CLASS_NAME); |
54 | // return (as_stream *) mod_lua_box_value(box); |
55 | // } |
56 | |
57 | static int mod_lua_stream_gc(lua_State * l) { |
58 | mod_lua_freebox(l, 1, CLASS_NAME); |
59 | return 0; |
60 | } |
61 | |
62 | static int mod_lua_stream_tostring(lua_State * l) { |
63 | as_stream * stream = mod_lua_tostream(l, 1); |
64 | char str[128] = { '\0' }; |
65 | snprintf(str, 128, "Stream<%p>" , stream); |
66 | lua_pushstring(l, str); |
67 | return 1; |
68 | } |
69 | |
70 | static int mod_lua_stream_read(lua_State * l) { |
71 | as_stream * stream = mod_lua_tostream(l, 1); |
72 | if ( stream ) { |
73 | as_val * val = as_stream_read(stream); |
74 | mod_lua_pushval(l, val ); |
75 | |
76 | // Client aggregation queries read data from server nodes and populate this stream. After that, |
77 | // the client has no use for this value. Therefore, destroy value after reading from this stream. |
78 | // Enable on client build only. |
79 | #ifdef AS_MOD_LUA_CLIENT |
80 | as_val_destroy(val); |
81 | #endif |
82 | |
83 | return 1; |
84 | } |
85 | else { |
86 | lua_pushnil(l); |
87 | return 1; |
88 | } |
89 | } |
90 | |
91 | static int mod_lua_stream_readable(lua_State * l) { |
92 | as_stream * stream = mod_lua_tostream(l, 1); |
93 | if ( stream ) { |
94 | lua_pushboolean(l, as_stream_readable(stream)); |
95 | return 1; |
96 | } |
97 | else { |
98 | lua_pushboolean(l, false); |
99 | return 1; |
100 | } |
101 | } |
102 | |
103 | static int mod_lua_stream_write(lua_State * l) { |
104 | as_stream * stream = mod_lua_tostream(l, 1); |
105 | if ( stream ) { |
106 | as_val * val = mod_lua_toval(l, 2); |
107 | if ( val == &as_nil ) { |
108 | // as_nil terminates the stream in Lua, |
109 | // while NULL terminates the stream in C, |
110 | // so we map the former to the latter here. |
111 | val = NULL; |
112 | } |
113 | int rc = as_stream_write(stream, val); |
114 | lua_pushinteger(l, rc); |
115 | return 1; |
116 | } |
117 | else { |
118 | lua_pushinteger(l, AS_STREAM_ERR); |
119 | return 1; |
120 | } |
121 | } |
122 | |
123 | static int mod_lua_stream_writable(lua_State * l) { |
124 | as_stream * stream = mod_lua_tostream(l, 1); |
125 | if ( stream ) { |
126 | lua_pushboolean(l, as_stream_readable(stream)); |
127 | return 1; |
128 | } |
129 | else { |
130 | lua_pushboolean(l, false); |
131 | return 1; |
132 | } |
133 | } |
134 | |
135 | /******************************************************************************* |
136 | * OBJECT TABLE |
137 | ******************************************************************************/ |
138 | |
139 | static const luaL_reg object_table[] = { |
140 | {"read" , mod_lua_stream_read}, |
141 | {"write" , mod_lua_stream_write}, |
142 | {"readable" , mod_lua_stream_readable}, |
143 | {"writable" , mod_lua_stream_writable}, |
144 | {"tostring" , mod_lua_stream_tostring}, |
145 | {0, 0} |
146 | }; |
147 | |
148 | static const luaL_reg object_metatable[] = { |
149 | {0, 0} |
150 | }; |
151 | |
152 | /******************************************************************************* |
153 | * CLASS TABLE |
154 | ******************************************************************************/ |
155 | |
156 | /* |
157 | static const luaL_reg class_table[] = { |
158 | {0, 0} |
159 | }; |
160 | */ |
161 | |
162 | static const luaL_reg class_metatable[] = { |
163 | {"__tostring" , mod_lua_stream_tostring}, |
164 | {"__gc" , mod_lua_stream_gc}, |
165 | {0, 0} |
166 | }; |
167 | |
168 | /******************************************************************************* |
169 | * REGISTER |
170 | ******************************************************************************/ |
171 | |
172 | int mod_lua_stream_register(lua_State * l) { |
173 | mod_lua_reg_object(l, OBJECT_NAME, object_table, object_metatable); |
174 | mod_lua_reg_class(l, CLASS_NAME, NULL, class_metatable); |
175 | return 1; |
176 | } |
177 | |