1 /*
2 This file is part of darktable,
3 Copyright (C) 2013-2020 darktable developers.
4
5 darktable is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 darktable is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with darktable. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "lua/types.h"
19 #include "common/darktable.h"
20 #include "common/file_location.h"
21 #include "control/control.h"
22 #include "lua/call.h"
23 #include <math.h>
24 #include <stdarg.h>
25 #include <string.h>
26
27 /*************/
28 /* TYPES */
29 /*************/
30
to_char_array(lua_State * L,luaA_Type type_id,void * c_out,int index,int size)31 static void to_char_array(lua_State *L, luaA_Type type_id, void *c_out, int index, int size)
32 {
33 size_t tgt_size;
34 const char *value = luaL_checklstring(L, index, &tgt_size);
35 if(tgt_size > size)
36 {
37 luaL_error(L, "string '%s' too long (max is %d)", value, size);
38 }
39 strncpy(c_out, value, size);
40 }
41
push_char_array(lua_State * L,luaA_Type type_id,const void * c_in)42 static int push_char_array(lua_State *L, luaA_Type type_id, const void *c_in)
43 {
44 lua_pushstring(L, c_in);
45 return 1;
46 }
47
to_char20(lua_State * L,luaA_Type type_id,void * c_out,int index)48 static void to_char20(lua_State *L, luaA_Type type_id, void *c_out, int index)
49 {
50 to_char_array(L, type_id, c_out, index, 20);
51 }
to_char32(lua_State * L,luaA_Type type_id,void * c_out,int index)52 static void to_char32(lua_State *L, luaA_Type type_id, void *c_out, int index)
53 {
54 to_char_array(L, type_id, c_out, index, 32);
55 }
to_char52(lua_State * L,luaA_Type type_id,void * c_out,int index)56 static void to_char52(lua_State *L, luaA_Type type_id, void *c_out, int index)
57 {
58 to_char_array(L, type_id, c_out, index, 52);
59 }
to_char64(lua_State * L,luaA_Type type_id,void * c_out,int index)60 static void to_char64(lua_State *L, luaA_Type type_id, void *c_out, int index)
61 {
62 to_char_array(L, type_id, c_out, index, 64);
63 }
to_char128(lua_State * L,luaA_Type type_id,void * c_out,int index)64 static void to_char128(lua_State *L, luaA_Type type_id, void *c_out, int index)
65 {
66 to_char_array(L, type_id, c_out, index, 128);
67 }
to_char256(lua_State * L,luaA_Type type_id,void * c_out,int index)68 static void to_char256(lua_State *L, luaA_Type type_id, void *c_out, int index)
69 {
70 to_char_array(L, type_id, c_out, index, 256);
71 }
to_char512(lua_State * L,luaA_Type type_id,void * c_out,int index)72 static void to_char512(lua_State *L, luaA_Type type_id, void *c_out, int index)
73 {
74 to_char_array(L, type_id, c_out, index, 512);
75 }
to_char1024(lua_State * L,luaA_Type type_id,void * c_out,int index)76 static void to_char1024(lua_State *L, luaA_Type type_id, void *c_out, int index)
77 {
78 to_char_array(L, type_id, c_out, index, 1024);
79 }
to_charfilename_length(lua_State * L,luaA_Type type_id,void * c_out,int index)80 static void to_charfilename_length(lua_State *L, luaA_Type type_id, void *c_out, int index)
81 {
82 to_char_array(L, type_id, c_out, index, DT_MAX_FILENAME_LEN);
83 }
to_charpath_length(lua_State * L,luaA_Type type_id,void * c_out,int index)84 static void to_charpath_length(lua_State *L, luaA_Type type_id, void *c_out, int index)
85 {
86 to_char_array(L, type_id, c_out, index, PATH_MAX);
87 }
push_protected_double(lua_State * L,luaA_Type type_id,const void * c_in)88 static int push_protected_double(lua_State *L, luaA_Type type_id, const void *c_in)
89 {
90 double value = *(double *)c_in;
91 if(!isnormal(value))
92 {
93 lua_pushnil(L);
94 }
95 else
96 {
97 lua_pushnumber(L, value);
98 }
99 return 1;
100 }
101
push_progress_double(lua_State * L,luaA_Type type_id,const void * c_in)102 static int push_progress_double(lua_State *L, luaA_Type type_id, const void *c_in)
103 {
104 double value = *(double *)c_in;
105 if(value < 0.0) value = 0.0;
106 if(value > 1.0) value = 1.0;
107 lua_pushnumber(L, value);
108 return 1;
109 }
110
to_progress_double(lua_State * L,luaA_Type type_id,void * c_out,int index)111 static void to_progress_double(lua_State *L, luaA_Type type_id, void *c_out, int index)
112 {
113 luaA_to_double(L, type_id, c_out, index);
114 if(*(double *)c_out < 0.0) *(double *)c_out = 0.0;
115 if(*(double *)c_out > 1.0) *(double *)c_out = 1.0;
116 }
117
118 /************************************/
119 /* METATBLE CALLBACKS FOR AUTOTYPES */
120 /************************************/
autotype_next(lua_State * L)121 static int autotype_next(lua_State *L)
122 {
123 /* CONVENTION
124 each block has the following stack on entry and exit
125 1 : the object
126 2 : the last entry ("next" convention)
127 each block should return according to "next" convention on success
128 each block should leave the key untouched if it doesn't know about it
129 each block should replace the key with "nil" if the key was the last entry it can handle
130
131 */
132 // printf("aaaaa %s %d\n",__FUNCTION__,__LINE__);
133 if(luaL_getmetafield(L, 1, "__len"))
134 {
135 lua_pushvalue(L, -3);
136 lua_call(L, 1, 1);
137 int length = lua_tonumber(L, -1);
138 lua_pop(L, 1);
139 int key = 0;
140 if(lua_isnil(L, -1) && length > 0)
141 {
142 key = 1;
143 }
144 else if(lua_isnumber(L, -1) && lua_tonumber(L, -1) < length)
145 {
146 key = lua_tonumber(L, -1) + 1;
147 }
148 else if(lua_isnumber(L, -1) && lua_tonumber(L, -1) == length)
149 {
150 // numbers are done, move-on to something else
151 lua_pop(L, 1);
152 lua_pushnil(L);
153 }
154 if(key)
155 {
156 lua_pop(L, 1);
157 lua_pushinteger(L, key);
158 lua_pushinteger(L, key);
159 lua_gettable(L, -3);
160 return 2;
161 }
162 }
163 // stack at this point : {object,key}
164 int key_in_get = false;
165 luaL_getmetafield(L, 1, "__get");
166 if(lua_isnil(L, -2))
167 {
168 key_in_get = true;
169 }
170 else
171 {
172 lua_pushvalue(L, -2);
173 lua_gettable(L, -2);
174 if(lua_isnil(L, -1))
175 {
176 key_in_get = false;
177 lua_pop(L, 2);
178 }
179 else
180 {
181 key_in_get = true;
182 lua_pop(L, 1);
183 }
184 }
185 if(key_in_get)
186 {
187 lua_pushvalue(L, -2);
188 int nil_found = false;
189 while(!nil_found)
190 {
191 if(lua_next(L, -2))
192 {
193 // we have a next
194 lua_pop(L, 1);
195 lua_pushvalue(L, -4);
196 lua_pushvalue(L, -2);
197 // hacky way to avoid a subfunction just to do a pcall around getting a value in a table
198 luaL_loadstring(L,"args ={...}; return args[1][args[2]]");
199 lua_insert(L,-3);
200 int result = dt_lua_treated_pcall(L,2,1);
201 if(result == LUA_OK)
202 {
203 return 2;
204 }
205 else
206 {
207 lua_pop(L, 1);
208 // and loop to find the next possible value
209 }
210 }
211 else
212 {
213 // key was the last for __get
214 lua_pop(L, 2);
215 lua_pushnil(L);
216 nil_found = true;
217 }
218 }
219 }
220
221 // stack at this point : {object,key}
222 if(lua_isnil(L, -1))
223 {
224 return 1;
225 }
226 else
227 {
228 return luaL_error(L, "invalid key to 'next' : %s", lua_tostring(L, 2));
229 }
230 }
231
232
233
autotype_pairs(lua_State * L)234 static int autotype_pairs(lua_State *L)
235 {
236 luaL_getmetafield(L, 1, "__next");
237 lua_pushvalue(L, -2);
238 lua_pushnil(L); // index set to null for reset
239 return 3;
240 }
241
autotype_index(lua_State * L)242 static int autotype_index(lua_State *L)
243 {
244 luaL_getmetafield(L, 1, "__get");
245 int pos_get = lua_gettop(L); // points at __get
246 lua_pushvalue(L, -2);
247 lua_gettable(L, -2);
248 if(lua_isnil(L, -1) && lua_isnumber(L, -3))
249 {
250 if(luaL_getmetafield(L, 1, "__number_index"))
251 {
252 lua_remove(L, -2);
253 }
254 }
255 if(lua_isnil(L, -1))
256 {
257 lua_pop(L, 1);
258 luaL_getmetafield(L, -3, "__luaA_TypeName");
259 return luaL_error(L, "field \"%s\" not found for type %s\n", lua_tostring(L, -3), lua_tostring(L, -1));
260 }
261 lua_pushvalue(L, -4);
262 lua_pushvalue(L, -4);
263 lua_call(L, 2, LUA_MULTRET);
264 lua_remove(L, pos_get);
265 return (lua_gettop(L) - pos_get + 1);
266 }
267
268
autotype_newindex(lua_State * L)269 static int autotype_newindex(lua_State *L)
270 {
271 luaL_getmetafield(L, 1, "__set");
272 int pos_set = lua_gettop(L); // points at __get
273 lua_pushvalue(L, -3);
274 lua_gettable(L, -2);
275 if(lua_isnil(L, -1) && lua_isnumber(L, -4))
276 {
277 if(luaL_getmetafield(L, -5, "__number_newindex"))
278 {
279 lua_remove(L, -2);
280 }
281 }
282 if(lua_isnil(L, -1))
283 {
284 lua_pop(L, 1);
285 luaL_getmetafield(L, -4, "__luaA_TypeName");
286 return luaL_error(L, "field \"%s\" can't be written for type %s\n", lua_tostring(L, -4),
287 lua_tostring(L, -1));
288 }
289 lua_pushvalue(L, -5);
290 lua_pushvalue(L, -5);
291 lua_pushvalue(L, -5);
292 lua_call(L, 3, LUA_MULTRET);
293 lua_remove(L, pos_set);
294 return (lua_gettop(L) - pos_set + 1);
295 }
296
297
autotype_tostring(lua_State * L)298 static int autotype_tostring(lua_State *L)
299 {
300 if(luaL_getmetafield(L,1,"__real_tostring")) {
301 lua_insert(L,1);
302 lua_call(L,1,1);
303 return 1;
304 } else {
305 char tmp[256];
306 luaL_getmetafield(L,1,"__luaA_TypeName");
307 snprintf(tmp,sizeof(tmp),"%s (%p)",lua_tostring(L,-1),lua_topointer(L,1));
308 lua_pushstring(L,tmp);
309 return 1;
310 }
311 }
312
313 /*************************/
314 /* PUSH AND TO FUNCTIONS */
315 /*************************/
316
full_pushfunc(lua_State * L,luaA_Type type_id,const void * cin)317 static int full_pushfunc(lua_State *L, luaA_Type type_id, const void *cin)
318 {
319 size_t type_size = luaA_typesize(L, type_id);
320 void *udata = lua_newuserdata(L, type_size);
321 lua_newtable(L);
322 lua_setuservalue(L, -2);
323 if(cin)
324 {
325 memcpy(udata, cin, type_size);
326 }
327 else
328 {
329 memset(udata, 0, type_size);
330 }
331 luaL_setmetatable(L, luaA_typename(L, type_id));
332
333 if(luaL_getmetafield(L, -1, "__init"))
334 {
335 lua_pushvalue(L, -2); // the new allocated object
336 lua_pushlightuserdata(L, (void *)cin); // forced to cast..
337 lua_call(L, 2, 0);
338 }
339 return 1;
340 }
341
full_tofunc(lua_State * L,luaA_Type type_id,void * cout,int index)342 static void full_tofunc(lua_State *L, luaA_Type type_id, void *cout, int index)
343 {
344 if(!dt_lua_isa_type(L,index,type_id)) {
345 char error_msg[256];
346 snprintf(error_msg,sizeof(error_msg),"%s expected",luaA_typename(L,type_id));
347 luaL_argerror(L,index,error_msg);
348 }
349 void* udata = lua_touserdata(L,index);
350 memcpy(cout, udata, luaA_typesize(L, type_id));
351 }
352
int_pushfunc(lua_State * L,luaA_Type type_id,const void * cin)353 static int int_pushfunc(lua_State *L, luaA_Type type_id, const void *cin)
354 {
355 luaL_getmetatable(L, luaA_typename(L, type_id));
356 luaL_getsubtable(L, -1, "__values");
357 int singleton = *(int *)cin;
358 lua_pushinteger(L, singleton);
359 lua_gettable(L, -2);
360 if(lua_isnoneornil(L, -1))
361 {
362 lua_pop(L, 1);
363 int *udata = lua_newuserdata(L, sizeof(int));
364 *udata = singleton;
365 luaL_setmetatable(L, luaA_typename(L, type_id));
366 lua_pushinteger(L, singleton);
367 // warning : no uservalue
368 lua_pushvalue(L, -2);
369 lua_settable(L, -4);
370 if(luaL_getmetafield(L, -1, "__init"))
371 {
372 lua_pushvalue(L, -2); // the new allocated object
373 lua_pushlightuserdata(L, (void *)cin); // forced to cast..
374 lua_call(L, 2, 0);
375 }
376 }
377 lua_remove(L, -2); //__values
378 lua_remove(L, -2); // metatable
379 return 1;
380 }
381
int_tofunc(lua_State * L,luaA_Type type_id,void * cout,int index)382 static void int_tofunc(lua_State *L, luaA_Type type_id, void *cout, int index)
383 {
384 if(!dt_lua_isa_type(L,index,type_id)) {
385 char error_msg[256];
386 snprintf(error_msg,sizeof(error_msg),"%s expected",luaA_typename(L,type_id));
387 luaL_argerror(L,index,error_msg);
388 }
389 void* udata = lua_touserdata(L,index);
390 memcpy(cout, udata, sizeof(int));
391 }
392
gpointer_pushfunc(lua_State * L,luaA_Type type_id,const void * cin)393 static int gpointer_pushfunc(lua_State *L, luaA_Type type_id, const void *cin)
394 {
395 gpointer singleton = *(gpointer *)cin;
396 if(!singleton) {
397 lua_pushnil(L);
398 return 1;
399 }
400 luaL_getsubtable(L, LUA_REGISTRYINDEX, "dt_lua_gpointer_values");
401 lua_pushlightuserdata(L, singleton);
402 lua_gettable(L, -2);
403 if(lua_isnoneornil(L, -1))
404 {
405 lua_pop(L, 1);
406 gpointer *udata = lua_newuserdata(L, sizeof(gpointer));
407 lua_newtable(L);
408 lua_setuservalue(L, -2);
409 *udata = singleton;
410 luaL_setmetatable(L, luaA_typename(L, type_id));
411 lua_pushlightuserdata(L, singleton);
412 lua_pushvalue(L, -2);
413 lua_settable(L, -4);
414 if(luaL_getmetafield(L, -1, "__init"))
415 {
416 lua_pushvalue(L, -2); // the new allocated object
417 lua_pushlightuserdata(L, (void *)cin); // forced to cast..
418 lua_call(L, 2, 0);
419 }
420 }
421 lua_remove(L, -2); //dt_lua_gpointer_values
422 return 1;
423 }
424
gpointer_tofunc(lua_State * L,luaA_Type type_id,void * cout,int index)425 static void gpointer_tofunc(lua_State *L, luaA_Type type_id, void *cout, int index)
426 {
427 if(!dt_lua_isa_type(L,index,type_id)) {
428 char error_msg[256];
429 snprintf(error_msg,sizeof(error_msg),"%s expected",luaA_typename(L,type_id));
430 luaL_argerror(L,index,error_msg);
431 }
432 gpointer* udata = lua_touserdata(L,index);
433 memcpy(cout, udata, sizeof(gpointer));
434 if(!*udata) {
435 luaL_error(L,"Attempting to access of type %s after its destruction\n",luaA_typename(L,type_id));
436 }
437 }
438
unknown_pushfunc(lua_State * L,luaA_Type type_id,const void * cin)439 static int unknown_pushfunc(lua_State *L, luaA_Type type_id, const void *cin)
440 {
441 gpointer singleton = *(gpointer *)cin;
442 if(!singleton) {
443 lua_pushnil(L);
444 return 1;
445 }
446 luaL_getsubtable(L, LUA_REGISTRYINDEX, "dt_lua_gpointer_values");
447 lua_pushlightuserdata(L, singleton);
448 lua_gettable(L, -2);
449 if(lua_isnoneornil(L, -1))
450 {
451 return luaL_error(L,"Attempting to push a pointer of unknown type on the stack\n");
452 }
453 lua_remove(L, -2); //dt_lua_gpointer_values
454 return 1;
455 }
456
457
458 /*****************/
459 /* TYPE CREATION */
460 /*****************/
dt_lua_type_register_type(lua_State * L,luaA_Type type_id,const char * name)461 void dt_lua_type_register_type(lua_State *L, luaA_Type type_id, const char *name)
462 {
463 luaL_getmetatable(L, luaA_typename(L, type_id)); // gets the metatable since it's supposed to exist
464 luaL_getsubtable(L, -1, "__get");
465 lua_pushvalue(L, -3);
466 lua_setfield(L, -2, name);
467 lua_pop(L, 1);
468
469 luaL_getsubtable(L, -1, "__set");
470 lua_pushvalue(L, -3);
471 lua_setfield(L, -2, name);
472 lua_pop(L, 3);
473 }
474
dt_lua_type_register_const_type(lua_State * L,luaA_Type type_id,const char * name)475 void dt_lua_type_register_const_type(lua_State *L, luaA_Type type_id, const char *name)
476 {
477 luaL_getmetatable(L, luaA_typename(L, type_id)); // gets the metatable since it's supposed to exist
478
479 luaL_getsubtable(L, -1, "__get");
480 lua_pushvalue(L, -3);
481 lua_setfield(L, -2, name);
482 lua_pop(L, 3);
483 }
484
dt_lua_type_register_number_const_type(lua_State * L,luaA_Type type_id)485 void dt_lua_type_register_number_const_type(lua_State *L, luaA_Type type_id)
486 {
487 luaL_getmetatable(L, luaA_typename(L, type_id)); // gets the metatable since it's supposed to exist
488
489 lua_pushvalue(L, -2);
490 lua_setfield(L, -2, "__number_index");
491
492 if(!lua_isnil(L, -3))
493 {
494 lua_pushvalue(L, -3);
495 lua_setfield(L, -2, "__len");
496 }
497
498 lua_pop(L, 3);
499 }
dt_lua_type_register_number_type(lua_State * L,luaA_Type type_id)500 void dt_lua_type_register_number_type(lua_State *L, luaA_Type type_id)
501 {
502 luaL_getmetatable(L, luaA_typename(L, type_id)); // gets the metatable since it's supposed to exist
503
504 lua_pushvalue(L, -2);
505 lua_setfield(L, -2, "__number_index");
506
507 lua_pushvalue(L, -2);
508 lua_setfield(L, -2, "__number_newindex");
509
510 if(!lua_isnil(L, -3))
511 {
512 lua_pushvalue(L, -3);
513 lua_setfield(L, -2, "__len");
514 }
515
516 lua_pop(L, 3);
517 }
518
dt_lua_type_member_luaautoc(lua_State * L)519 int dt_lua_type_member_luaautoc(lua_State *L)
520 {
521 const char *member_name = luaL_checkstring(L, 2);
522 luaL_getmetafield(L, 1, "__luaA_Type");
523 luaA_Type my_type = luaL_checkinteger(L, -1);
524 lua_pop(L, 1);
525 void *object = lua_touserdata(L, 1);
526 if(lua_gettop(L) != 3)
527 {
528 luaA_struct_push_member_name_type(L, my_type, member_name, object);
529 return 1;
530 }
531 else
532 {
533 luaA_struct_to_member_name_type(L, my_type, member_name, object, 3);
534 return 0;
535 }
536 }
537
dt_lua_type_register_struct_type(lua_State * L,luaA_Type type_id)538 void dt_lua_type_register_struct_type(lua_State *L, luaA_Type type_id)
539 {
540 const char *member_name = luaA_struct_next_member_name_type(L, type_id, LUAA_INVALID_MEMBER_NAME);
541 while(member_name != LUAA_INVALID_MEMBER_NAME)
542 {
543 lua_pushvalue(L, -1);
544 luaA_Type member_type = luaA_struct_typeof_member_name_type(L, type_id, member_name);
545 if(luaA_conversion_to_registered_type(L, member_type) || luaA_struct_registered_type(L, member_type)
546 || luaA_enum_registered_type(L, member_type))
547 {
548 dt_lua_type_register_type(L, type_id, member_name);
549 }
550 else
551 {
552 dt_lua_type_register_const_type(L, type_id, member_name);
553 }
554 member_name = luaA_struct_next_member_name_type(L, type_id, member_name);
555 }
556 lua_pop(L, 1);
557 }
558
559
dt_lua_type_member_common(lua_State * L)560 int dt_lua_type_member_common(lua_State *L)
561 {
562 if(lua_gettop(L) != 2)
563 {
564 luaL_getmetafield(L, 1, "__luaA_TypeName");
565 return luaL_error(L, "field \"%s\" can't be written for type %s\n", lua_tostring(L, 2),
566 lua_tostring(L, -1));
567 }
568 lua_pushvalue(L, lua_upvalueindex(1));
569 return 1;
570 }
571
dt_lua_type_register_parent_type(lua_State * L,luaA_Type type_id,luaA_Type parent_type_id)572 void dt_lua_type_register_parent_type(lua_State *L, luaA_Type type_id, luaA_Type parent_type_id)
573 {
574 luaL_getmetatable(L, luaA_typename(L, type_id)); // gets the metatable since it's supposed to exist
575 luaL_getmetatable(L, luaA_typename(L, parent_type_id)); // gets the metatable since it's supposed to exist
576
577 lua_pushvalue(L, -1);
578 lua_setfield(L, -3, "__luaA_ParentMetatable");
579
580 lua_getfield(L, -2, "__get");
581 lua_getfield(L, -2, "__get");
582 lua_pushnil(L); /* first key */
583 while(lua_next(L, -2) != 0)
584 {
585 lua_getfield(L,-4,lua_tostring(L,-2));
586 if(lua_isnil(L,-1)) {
587 lua_pop(L,1);
588 lua_setfield(L, -4, lua_tostring(L,-2));
589 } else {
590 lua_pop(L,2);
591 }
592 }
593 lua_pop(L, 2);
594
595 lua_getfield(L, -2, "__set");
596 lua_getfield(L, -2, "__set");
597 lua_pushnil(L); /* first key */
598 while(lua_next(L, -2) != 0)
599 {
600 lua_getfield(L,-4,lua_tostring(L,-2));
601 if(lua_isnil(L,-1)) {
602 lua_pop(L,1);
603 lua_setfield(L, -4, lua_tostring(L,-2));
604 } else {
605 lua_pop(L,2);
606 }
607 }
608 lua_pop(L, 2);
609
610 lua_pushnil(L); /* first key */
611 while(lua_next(L, -2) != 0)
612 {
613 lua_getfield(L,-4,lua_tostring(L,-2));
614 if(lua_isnil(L,-1)) {
615 lua_pop(L,1);
616 lua_setfield(L, -4, lua_tostring(L,-2));
617 } else {
618 lua_pop(L,2);
619 }
620 }
621
622
623 lua_pop(L, 2);
624 }
625
init_metatable(lua_State * L,luaA_Type type_id)626 static void init_metatable(lua_State *L, luaA_Type type_id)
627 {
628 luaL_newmetatable(L, luaA_typename(L, type_id));
629
630 lua_pushstring(L, luaA_typename(L, type_id));
631 lua_setfield(L, -2, "__luaA_TypeName");
632
633 lua_pushinteger(L, type_id);
634 lua_setfield(L, -2, "__luaA_Type");
635
636 lua_pushvalue(L, -1);
637 lua_pushcclosure(L, autotype_next, 1);
638 lua_setfield(L, -2, "__next");
639
640 lua_pushvalue(L, -1);
641 lua_pushcclosure(L, autotype_pairs, 1);
642 lua_setfield(L, -2, "__pairs");
643
644 lua_pushvalue(L, -1);
645 lua_pushcclosure(L, autotype_index, 1);
646 lua_setfield(L, -2, "__index");
647
648 lua_pushvalue(L, -1);
649 lua_pushcclosure(L, autotype_newindex, 1);
650 lua_setfield(L, -2, "__newindex");
651
652 lua_newtable(L);
653 lua_setfield(L, -2, "__get");
654
655 lua_newtable(L);
656 lua_setfield(L, -2, "__set");
657
658 lua_pushvalue(L, -1);
659 lua_pushcclosure(L, autotype_tostring, 1);
660 lua_setfield(L, -2, "__tostring");
661
662 // leave metatable on top of stack
663 }
664
665
dt_lua_init_type_type(lua_State * L,luaA_Type type_id)666 luaA_Type dt_lua_init_type_type(lua_State *L, luaA_Type type_id)
667 {
668 init_metatable(L, type_id);
669 lua_pop(L, 1);
670 luaA_conversion_type(L, type_id, full_pushfunc, full_tofunc);
671 return type_id;
672 }
673
dt_lua_init_singleton(lua_State * L,const char * unique_name,void * data)674 luaA_Type dt_lua_init_singleton(lua_State *L, const char *unique_name, void *data)
675 {
676 char tmp_name[1024];
677 snprintf(tmp_name, sizeof(tmp_name), "dt_lua_singleton_%s", unique_name);
678
679 luaA_Type type_id = luaA_type_add(L, tmp_name, sizeof(void *));
680 init_metatable(L, type_id);
681
682 void **udata = lua_newuserdata(L, sizeof(void *));
683 lua_newtable(L);
684 lua_setuservalue(L, -2);
685 if(!data)
686 {
687 memset(udata, 0, sizeof(void *));
688 }
689 else
690 {
691 *udata = data;
692 luaL_getsubtable(L, LUA_REGISTRYINDEX, "dt_lua_gpointer_values");
693 lua_pushlightuserdata(L, data);
694 lua_pushvalue(L,-3);
695 lua_settable(L,-3);
696 lua_pop(L,1);
697 }
698
699 lua_pushvalue(L, -1);
700 luaL_setmetatable(L, tmp_name);
701 lua_setfield(L, -3, "__singleton");
702 if(luaL_getmetafield(L, -1, "__init"))
703 {
704 lua_pushvalue(L, -2); // the new allocated object
705 lua_pushlightuserdata(L, (void *)data); // forced to cast..
706 lua_call(L, 2, 0);
707 }
708 lua_remove(L, -2);
709
710 return type_id;
711 }
712
713
wrapped_index(lua_State * L)714 static int wrapped_index(lua_State *L)
715 {
716 luaL_getmetafield(L, 1, "__pusher");
717 lua_pushvalue(L, 1);
718 lua_call(L, 1, 1);
719 lua_pushvalue(L, 2);
720 lua_gettable(L, -2);
721 lua_remove(L, 1);
722 lua_remove(L, 1);
723 return 1;
724 }
725
wrapped_pairs(lua_State * L)726 static int wrapped_pairs(lua_State *L)
727 {
728 luaL_getmetafield(L, 1, "__pusher");
729 lua_pushvalue(L, 1);
730 lua_call(L, 1, 1);
731 luaL_getmetafield(L, -1, "__pairs");
732 lua_pushvalue(L, -2);
733 lua_call(L, 1, 3);
734 return 3;
735 }
wrapped_newindex(lua_State * L)736 static int wrapped_newindex(lua_State *L)
737 {
738 return luaL_error(L, "TBSL");
739 }
wrapped_tostring(lua_State * L)740 static int wrapped_tostring(lua_State *L)
741 {
742 return luaL_error(L, "TBSL");
743 }
744
745
dt_lua_init_wrapped_singleton(lua_State * L,lua_CFunction pusher,lua_CFunction getter,const char * unique_name,void * data)746 luaA_Type dt_lua_init_wrapped_singleton(lua_State *L, lua_CFunction pusher, lua_CFunction getter,
747 const char *unique_name, void *data)
748 {
749 luaA_Type result = dt_lua_init_singleton(L, unique_name, data);
750 lua_getmetatable(L, -1);
751 lua_pushcfunction(L, wrapped_index);
752 lua_setfield(L, -2, "__index");
753 lua_pushcfunction(L, wrapped_newindex);
754 lua_setfield(L, -2, "__newindex");
755 lua_pushcfunction(L, wrapped_pairs);
756 lua_setfield(L, -2, "__pairs");
757 lua_pushcfunction(L, wrapped_tostring);
758 lua_setfield(L, -2, "__tostring");
759 lua_pushcfunction(L, pusher);
760 lua_setfield(L, -2, "__pusher");
761 lua_pushcfunction(L, getter);
762 lua_setfield(L, -2, "__getter");
763 lua_pop(L, 1);
764 return result;
765 }
766
dt_lua_init_int_type_type(lua_State * L,luaA_Type type_id)767 luaA_Type dt_lua_init_int_type_type(lua_State *L, luaA_Type type_id)
768 {
769 init_metatable(L, type_id);
770 lua_newtable(L);
771 // metatable of __values
772 lua_newtable(L);
773 lua_pushstring(L, "kv");
774 lua_setfield(L, -2, "__mode");
775 lua_setmetatable(L, -2);
776
777 lua_setfield(L, -2, "__values");
778 lua_pop(L, 1);
779 luaA_conversion_type(L, type_id, int_pushfunc, int_tofunc);
780 return type_id;
781 }
782
gpointer_wrapper(lua_State * L)783 static int gpointer_wrapper(lua_State*L)
784 {
785 gpointer *udata = (gpointer*)lua_touserdata(L,1);
786 if(!*udata) {
787 luaL_getmetafield(L,1,"__luaA_TypeName");
788 luaL_error(L,"Attempting to access an invalid object of type %s",lua_tostring(L,-1));
789 }
790 lua_CFunction callback = lua_tocfunction(L,lua_upvalueindex(1));
791 return callback(L);
792 }
793
794
dt_lua_init_gpointer_type_type(lua_State * L,luaA_Type type_id)795 luaA_Type dt_lua_init_gpointer_type_type(lua_State *L, luaA_Type type_id)
796 {
797 init_metatable(L, type_id);
798
799 lua_getfield(L,-1,"__next");
800 lua_pushcclosure(L, gpointer_wrapper,1);
801 lua_setfield(L, -2, "__next");
802
803 lua_getfield(L,-1,"__index");
804 lua_pushcclosure(L, gpointer_wrapper,1);
805 lua_setfield(L, -2, "__index");
806
807 lua_getfield(L,-1,"__newindex");
808 lua_pushcclosure(L, gpointer_wrapper,1);
809 lua_setfield(L, -2, "__newindex");
810
811 lua_getfield(L,-1,"__pairs");
812 lua_pushcclosure(L, gpointer_wrapper,1);
813 lua_setfield(L, -2, "__pairs");
814
815 lua_getfield(L,-1,"__tostring");
816 lua_pushcclosure(L, gpointer_wrapper,1);
817 lua_setfield(L, -2, "__tostring");
818
819 lua_pop(L, 1);
820
821 luaA_conversion_type(L, type_id, gpointer_pushfunc, gpointer_tofunc);
822 return type_id;
823 }
824
dt_lua_type_gpointer_alias_type(lua_State * L,luaA_Type type_id,void * pointer,void * alias)825 void dt_lua_type_gpointer_alias_type(lua_State*L,luaA_Type type_id,void* pointer,void* alias)
826 {
827 luaL_getsubtable(L, LUA_REGISTRYINDEX, "dt_lua_gpointer_values");
828 lua_pushlightuserdata(L, pointer);
829 lua_gettable(L, -2);
830 if(lua_isnoneornil(L, -1))
831 {
832 luaL_error(L,"Adding an alias to an unknown object for type %s",luaA_typename(L,type_id));
833 }
834 lua_pushlightuserdata(L,alias);
835 lua_insert(L,-2);
836 lua_settable(L,-3);
837 lua_pop(L,1);
838
839
840 }
841
dt_lua_type_gpointer_drop(lua_State * L,void * pointer)842 void dt_lua_type_gpointer_drop(lua_State*L, void* pointer)
843 {
844 luaL_getsubtable(L, LUA_REGISTRYINDEX, "dt_lua_gpointer_values");
845
846 lua_pushlightuserdata(L, pointer);
847 lua_gettable(L,-2);
848 gpointer *udata = (gpointer*)lua_touserdata(L,-1);
849 if(lua_isnil(L,-1)) {
850 lua_pop(L,2);
851 return; // this table is weak, the object has been gc
852 }
853 *udata = NULL;
854 lua_pop(L,1);
855
856 lua_pushlightuserdata(L, pointer);
857 lua_pushnil(L);
858 lua_settable(L,-3);
859
860 lua_pop(L,1);
861
862 }
863
dt_lua_isa_type(lua_State * L,int index,luaA_Type type_id)864 gboolean dt_lua_isa_type(lua_State *L, int index, luaA_Type type_id)
865 {
866 if(!luaL_getmetafield(L, index, "__luaA_Type")) return false;
867 int obj_type = luaL_checkinteger(L, -1);
868 lua_pop(L, 1);
869 return dt_lua_typeisa_type(L, obj_type, type_id);
870 }
871
dt_lua_typeisa_type(lua_State * L,luaA_Type obj_type,luaA_Type type_id)872 gboolean dt_lua_typeisa_type(lua_State *L, luaA_Type obj_type, luaA_Type type_id)
873 {
874 if(obj_type == type_id) return true;
875 luaL_getmetatable(L, luaA_typename(L, obj_type));
876 lua_getfield(L, -1, "__luaA_ParentMetatable");
877 if(lua_isnil(L, -1))
878 {
879 lua_pop(L, 2);
880 return false;
881 }
882 lua_getfield(L, -1, "__luaA_Type");
883 int parent_type = luaL_checkinteger(L, -1);
884 lua_pop(L, 3);
885 return dt_lua_typeisa_type(L, parent_type, type_id);
886 }
887
dt_lua_type_setmetafield_type(lua_State * L,luaA_Type type_id,const char * method_name)888 void dt_lua_type_setmetafield_type(lua_State*L,luaA_Type type_id,const char* method_name)
889 {
890 // These metafields should never be overridden by user code
891 if(
892 !strcmp(method_name,"__index") ||
893 !strcmp(method_name,"__newindex") ||
894 !strcmp(method_name,"__number_index") ||
895 !strcmp(method_name,"__number_newindex") ||
896 !strcmp(method_name,"__pairs") ||
897 !strcmp(method_name,"__next") ||
898 !strcmp(method_name,"__get") ||
899 !strcmp(method_name,"__set") ||
900 !strcmp(method_name,"__len") ||
901 !strcmp(method_name,"__luaA_Type") ||
902 !strcmp(method_name,"__luaA_TypeName") ||
903 !strcmp(method_name,"__luaA_ParentMetatable") ||
904 !strcmp(method_name,"__init") ||
905 !strcmp(method_name,"__values") ||
906 !strcmp(method_name,"__singleton") ||
907 !strcmp(method_name,"__pusher") ||
908 !strcmp(method_name,"__getter") ||
909 !strcmp(method_name,"__mode") ||
910 0) {
911 luaL_error(L,"non-core lua code is not allowed to change meta-field %s\n",method_name);
912 } else if(!strcmp(method_name,"__tostring")) {
913 luaL_getmetatable(L, luaA_typename(L, type_id));
914 lua_pushvalue(L,-2);
915 lua_setfield(L, -2, "__real_tostring");
916 lua_pop(L, 2); // pop the metatable and the value
917 return;
918 // whitelist for specific types
919 } else if(
920 // if you add a type here, make sure it handles inheritance of metamethods itself
921 // typically, set the metamethod not for the parent type but just after inheritance
922 ( !strcmp(method_name,"__associated_object")&& dt_lua_typeisa_type(L,type_id,luaA_type_find(L,"dt_imageio_module_format_t"))) ||
923 ( !strcmp(method_name,"__associated_object")&& dt_lua_typeisa_type(L,type_id,luaA_type_find(L,"dt_imageio_module_storage_t"))) ||
924 ( !strcmp(method_name,"__gc")&& dt_lua_typeisa_type(L,type_id,luaA_type_find(L,"dt_style_t"))) ||
925 ( !strcmp(method_name,"__gc")&& dt_lua_typeisa_type(L,type_id,luaA_type_find(L,"dt_style_item_t"))) ||
926 ( !strcmp(method_name,"__gc")&& dt_lua_typeisa_type(L,type_id,luaA_type_find(L,"lua_widget"))) ||
927 ( !strcmp(method_name,"__call")&& dt_lua_typeisa_type(L,type_id,luaA_type_find(L,"lua_widget"))) ||
928 ( !strcmp(method_name,"__gtk_signals")&& dt_lua_typeisa_type(L,type_id,luaA_type_find(L,"lua_widget"))) ||
929 0) {
930 // Nothing to be done
931 } else {
932 luaL_error(L,"metafield not handled :%s for type %s\n",method_name,luaA_typename(L,type_id));
933 }
934 luaL_getmetatable(L, luaA_typename(L, type_id));
935 lua_pushvalue(L,-2);
936 lua_setfield(L, -2, method_name);
937 lua_pop(L, 2); // pop the metatable and the value
938 }
939
dt_lua_init_early_types(lua_State * L)940 int dt_lua_init_early_types(lua_State *L)
941 {
942 luaA_conversion(L, char_20, push_char_array, to_char20);
943 luaA_conversion_push(L, const char_20, push_char_array);
944 luaA_conversion(L, char_32, push_char_array, to_char32);
945 luaA_conversion_push(L, const char_32, push_char_array);
946 luaA_conversion(L, char_52, push_char_array, to_char52);
947 luaA_conversion_push(L, const char_52, push_char_array);
948 luaA_conversion(L, char_64, push_char_array, to_char64);
949 luaA_conversion_push(L, const char_64, push_char_array);
950 luaA_conversion(L, char_128, push_char_array, to_char128);
951 luaA_conversion_push(L, const char_128, push_char_array);
952 luaA_conversion(L, char_256, push_char_array, to_char256);
953 luaA_conversion_push(L, const char_256, push_char_array);
954 luaA_conversion(L, char_512, push_char_array, to_char512);
955 luaA_conversion_push(L, const char_512, push_char_array);
956 luaA_conversion(L, char_1024, push_char_array, to_char1024);
957 luaA_conversion_push(L, const char_1024, push_char_array);
958 luaA_conversion(L, char_filename_length, push_char_array, to_charfilename_length);
959 luaA_conversion_push(L, const char_filename_length, push_char_array);
960 luaA_conversion(L, char_path_length, push_char_array, to_charpath_length);
961 luaA_conversion_push(L, const char_path_length, push_char_array);
962 luaA_conversion(L, int32_t, luaA_push_int, luaA_to_int);
963 luaA_conversion_push(L, const int32_t, luaA_push_int);
964 luaA_conversion_push(L, const_string, luaA_push_const_char_ptr);
965 luaA_conversion(L, protected_double, push_protected_double, luaA_to_double);
966 luaA_conversion(L, progress_double, push_progress_double, to_progress_double);
967
968 luaA_conversion_push_type(L, luaA_type_add(L,"unknown",sizeof(void*)), unknown_pushfunc);
969 // table of gpointer values
970 lua_newtable(L);
971 lua_newtable(L);
972 lua_pushstring(L, "kv");
973 lua_setfield(L, -2, "__mode");
974 lua_setmetatable(L, -2);
975
976 lua_setfield(L, LUA_REGISTRYINDEX, "dt_lua_gpointer_values");
977
978 luaA_enum(L,dt_lua_orientation_t);
979 luaA_enum_value_name(L,dt_lua_orientation_t,GTK_ORIENTATION_HORIZONTAL,"horizontal");
980 luaA_enum_value_name(L,dt_lua_orientation_t,GTK_ORIENTATION_VERTICAL,"vertical");
981
982 luaA_enum(L, dt_lua_align_t);
983 luaA_enum_value_name(L, dt_lua_align_t, GTK_ALIGN_FILL, "fill");
984 luaA_enum_value_name(L, dt_lua_align_t, GTK_ALIGN_START, "start");
985 luaA_enum_value_name(L, dt_lua_align_t, GTK_ALIGN_END, "end");
986 luaA_enum_value_name(L, dt_lua_align_t, GTK_ALIGN_CENTER, "center");
987 luaA_enum_value_name(L, dt_lua_align_t, GTK_ALIGN_BASELINE, "baseline");
988
989 luaA_enum(L, dt_lua_ellipsize_mode_t);
990 luaA_enum_value_name(L, dt_lua_ellipsize_mode_t, PANGO_ELLIPSIZE_NONE, "none");
991 luaA_enum_value_name(L, dt_lua_ellipsize_mode_t, PANGO_ELLIPSIZE_START, "start");
992 luaA_enum_value_name(L, dt_lua_ellipsize_mode_t, PANGO_ELLIPSIZE_MIDDLE, "middle");
993 luaA_enum_value_name(L, dt_lua_ellipsize_mode_t, PANGO_ELLIPSIZE_END, "end");
994
995 return 0;
996 }
997
998 // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
999 // vim: shiftwidth=2 expandtab tabstop=2 cindent
1000 // kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
1001