Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/lutok/state.cpp
102644 views
1
// Copyright 2011 Google Inc.
2
// All rights reserved.
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are
6
// met:
7
//
8
// * Redistributions of source code must retain the above copyright
9
// notice, this list of conditions and the following disclaimer.
10
// * Redistributions in binary form must reproduce the above copyright
11
// notice, this list of conditions and the following disclaimer in the
12
// documentation and/or other materials provided with the distribution.
13
// * Neither the name of Google Inc. nor the names of its contributors
14
// may be used to endorse or promote products derived from this software
15
// without specific prior written permission.
16
//
17
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29
extern "C" {
30
#include <unistd.h>
31
}
32
33
#include <cassert>
34
#include <cstring>
35
36
#include "c_gate.hpp"
37
#include "exceptions.hpp"
38
#include "state.ipp"
39
40
41
namespace {
42
43
44
/// Wrapper around lua_getglobal to run in a protected environment.
45
///
46
/// \pre stack(-1) is the name of the global to get.
47
/// \post stack(-1) is the value of the global.
48
///
49
/// \param state The Lua C API state.
50
///
51
/// \return The number of return values pushed onto the stack.
52
static int
53
protected_getglobal(lua_State* state)
54
{
55
lua_getglobal(state, lua_tostring(state, -1));
56
return 1;
57
}
58
59
60
/// Wrapper around lua_gettable to run in a protected environment.
61
///
62
/// \pre stack(-2) is the table to get the element from.
63
/// \pre stack(-1) is the table index.
64
/// \post stack(-1) is the value of stack(-2)[stack(-1)].
65
///
66
/// \param state The Lua C API state.
67
///
68
/// \return The number of return values pushed onto the stack.
69
static int
70
protected_gettable(lua_State* state)
71
{
72
lua_gettable(state, -2);
73
return 1;
74
}
75
76
77
/// Wrapper around lua_next to run in a protected environment.
78
///
79
/// \pre stack(-2) is the table to get the next element from.
80
/// \pre stack(-1) is the last processed key.
81
/// \post stack(-1) is the value of next(stack(-2), stack(-1)).
82
///
83
/// \param state The Lua C API state.
84
///
85
/// \return The number of return values pushed onto the stack.
86
static int
87
protected_next(lua_State* state)
88
{
89
const int more = lua_next(state, -2) != 0;
90
lua_pushboolean(state, more);
91
return more ? 3 : 1;
92
}
93
94
95
/// Wrapper around lua_setglobal to run in a protected environment.
96
///
97
/// \pre stack(-2) is the name of the global to set.
98
/// \pre stack(-1) is the value to set the global to.
99
///
100
/// \param state The Lua C API state.
101
///
102
/// \return The number of return values pushed onto the stack.
103
static int
104
protected_setglobal(lua_State* state)
105
{
106
lua_setglobal(state, lua_tostring(state, -2));
107
return 0;
108
}
109
110
111
/// Wrapper around lua_settable to run in a protected environment.
112
///
113
/// \pre stack(-3) is the table to set the element into.
114
/// \pre stack(-2) is the table index.
115
/// \pre stack(-1) is the value to set.
116
///
117
/// \param state The Lua C API state.
118
///
119
/// \return The number of return values pushed onto the stack.
120
static int
121
protected_settable(lua_State* state)
122
{
123
lua_settable(state, -3);
124
return 0;
125
}
126
127
128
/// Calls a C++ Lua function from a C calling environment.
129
///
130
/// Any errors reported by the C++ function are caught and reported to the
131
/// caller as Lua errors.
132
///
133
/// \param function The C++ function to call.
134
/// \param raw_state The raw Lua state.
135
///
136
/// \return The number of return values pushed onto the Lua stack by the
137
/// function.
138
static int
139
call_cxx_function_from_c(lutok::cxx_function function,
140
lua_State* raw_state) throw()
141
{
142
char error_buf[1024];
143
144
try {
145
lutok::state state = lutok::state_c_gate::connect(raw_state);
146
return function(state);
147
} catch (const std::exception& e) {
148
std::strncpy(error_buf, e.what(), sizeof(error_buf));
149
} catch (...) {
150
std::strncpy(error_buf, "Unhandled exception in Lua C++ hook",
151
sizeof(error_buf));
152
}
153
error_buf[sizeof(error_buf) - 1] = '\0';
154
// We raise the Lua error from outside the try/catch context and we use
155
// a stack-based buffer to hold the message to ensure that we do not leak
156
// any C++ objects (and, as a likely result, memory) when Lua performs its
157
// longjmp.
158
return luaL_error(raw_state, "%s", error_buf);
159
}
160
161
162
/// Lua glue to call a C++ closure.
163
///
164
/// This Lua binding is actually a closure that we have constructed from the
165
/// state.push_cxx_closure() method. The closure contains the same upvalues
166
/// provided by the user plus an extra upvalue that contains the address of the
167
/// C++ function we have to call. All we do here is safely delegate the
168
/// execution to the wrapped C++ closure.
169
///
170
/// \param raw_state The Lua C API state.
171
///
172
/// \return The number of return values of the called closure.
173
static int
174
cxx_closure_trampoline(lua_State* raw_state)
175
{
176
lutok::state state = lutok::state_c_gate::connect(raw_state);
177
178
int nupvalues;
179
{
180
lua_Debug debug;
181
lua_getstack(raw_state, 0, &debug);
182
lua_getinfo(raw_state, "u", &debug);
183
nupvalues = debug.nups;
184
}
185
186
lutok::cxx_function* function = state.to_userdata< lutok::cxx_function >(
187
state.upvalue_index(nupvalues));
188
return call_cxx_function_from_c(*function, raw_state);
189
}
190
191
192
/// Lua glue to call a C++ function.
193
///
194
/// This Lua binding is actually a closure that we have constructed from the
195
/// state.push_cxx_function() method. The closure has a single upvalue that
196
/// contains the address of the C++ function we have to call. All we do here is
197
/// safely delegate the execution to the wrapped C++ function.
198
///
199
/// \param raw_state The Lua C API state.
200
///
201
/// \return The number of return values of the called function.
202
static int
203
cxx_function_trampoline(lua_State* raw_state)
204
{
205
lutok::state state = lutok::state_c_gate::connect(raw_state);
206
lutok::cxx_function* function = state.to_userdata< lutok::cxx_function >(
207
state.upvalue_index(1));
208
return call_cxx_function_from_c(*function, raw_state);
209
}
210
211
212
} // anonymous namespace
213
214
215
const int lutok::registry_index = LUA_REGISTRYINDEX;
216
217
218
/// Internal implementation for lutok::state.
219
struct lutok::state::impl {
220
/// The Lua internal state.
221
lua_State* lua_state;
222
223
/// Whether we own the state or not (to decide if we close it).
224
bool owned;
225
226
/// Constructor.
227
///
228
/// \param lua_ The Lua internal state.
229
/// \param owned_ Whether we own the state or not.
230
impl(lua_State* lua_, bool owned_) :
231
lua_state(lua_),
232
owned(owned_)
233
{
234
}
235
};
236
237
238
/// Initializes the Lua state.
239
///
240
/// You must share the same state object alongside the lifetime of your Lua
241
/// session. As soon as the object is destroyed, the session is terminated.
242
lutok::state::state(void)
243
{
244
lua_State* lua = luaL_newstate();
245
if (lua == NULL)
246
throw lutok::error("lua open failed");
247
_pimpl.reset(new impl(lua, true));
248
}
249
250
251
/// Initializes the Lua state from an existing raw state.
252
///
253
/// Instances constructed using this method do NOT own the raw state. This
254
/// means that, on exit, the state will not be destroyed.
255
///
256
/// \param raw_state_ The raw Lua state to wrap.
257
lutok::state::state(void* raw_state_) :
258
_pimpl(new impl(reinterpret_cast< lua_State* >(raw_state_), false))
259
{
260
}
261
262
263
/// Destructor for the Lua state.
264
///
265
/// Closes the session unless it has already been closed by calling the
266
/// close() method. It is recommended to explicitly close the session in the
267
/// code.
268
lutok::state::~state(void)
269
{
270
if (_pimpl->owned && _pimpl->lua_state != NULL)
271
close();
272
}
273
274
275
/// Terminates this Lua session.
276
///
277
/// It is recommended to call this instead of relying on the destructor to do
278
/// the cleanup, but it is not a requirement to use close().
279
///
280
/// \pre close() has not yet been called.
281
/// \pre The Lua stack is empty. This is not truly necessary but ensures that
282
/// our code is consistent and clears the stack explicitly.
283
void
284
lutok::state::close(void)
285
{
286
assert(_pimpl->lua_state != NULL);
287
assert(lua_gettop(_pimpl->lua_state) == 0);
288
lua_close(_pimpl->lua_state);
289
_pimpl->lua_state = NULL;
290
}
291
292
293
/// Wrapper around lua_getglobal.
294
///
295
/// \param name The second parameter to lua_getglobal.
296
///
297
/// \throw api_error If lua_getglobal fails.
298
///
299
/// \warning Terminates execution if there is not enough memory to manipulate
300
/// the Lua stack.
301
void
302
lutok::state::get_global(const std::string& name)
303
{
304
lua_pushcfunction(_pimpl->lua_state, protected_getglobal);
305
lua_pushstring(_pimpl->lua_state, name.c_str());
306
if (lua_pcall(_pimpl->lua_state, 1, 1, 0) != 0)
307
throw lutok::api_error::from_stack(*this, "lua_getglobal");
308
}
309
310
311
/// Pushes a reference to the global table onto the stack.
312
///
313
/// This is a wrapper around the incompatible differences between Lua 5.1 and
314
/// 5.2 to access to the globals table.
315
///
316
/// \post state(-1) Contains the reference to the globals table.
317
void
318
lutok::state::get_global_table(void)
319
{
320
#if LUA_VERSION_NUM >= 502
321
lua_pushvalue(_pimpl->lua_state, registry_index);
322
lua_pushinteger(_pimpl->lua_state, LUA_RIDX_GLOBALS);
323
lua_gettable(_pimpl->lua_state, -2);
324
lua_remove(_pimpl->lua_state, -2);
325
#else
326
lua_pushvalue(_pimpl->lua_state, LUA_GLOBALSINDEX);
327
#endif
328
}
329
330
331
/// Wrapper around luaL_getmetafield.
332
///
333
/// \param index The second parameter to luaL_getmetafield.
334
/// \param name The third parameter to luaL_getmetafield.
335
///
336
/// \return The return value of luaL_getmetafield.
337
///
338
/// \warning Terminates execution if there is not enough memory to manipulate
339
/// the Lua stack.
340
bool
341
lutok::state::get_metafield(const int index, const std::string& name)
342
{
343
return luaL_getmetafield(_pimpl->lua_state, index, name.c_str()) != 0;
344
}
345
346
347
/// Wrapper around lua_getmetatable.
348
///
349
/// \param index The second parameter to lua_getmetatable.
350
///
351
/// \return The return value of lua_getmetatable.
352
bool
353
lutok::state::get_metatable(const int index)
354
{
355
return lua_getmetatable(_pimpl->lua_state, index) != 0;
356
}
357
358
359
/// Wrapper around lua_gettable.
360
///
361
/// \param index The second parameter to lua_gettable.
362
///
363
/// \throw api_error If lua_gettable fails.
364
///
365
/// \warning Terminates execution if there is not enough memory to manipulate
366
/// the Lua stack.
367
void
368
lutok::state::get_table(const int index)
369
{
370
assert(lua_gettop(_pimpl->lua_state) >= 2);
371
lua_pushcfunction(_pimpl->lua_state, protected_gettable);
372
lua_pushvalue(_pimpl->lua_state, index < 0 ? index - 1 : index);
373
lua_pushvalue(_pimpl->lua_state, -3);
374
if (lua_pcall(_pimpl->lua_state, 2, 1, 0) != 0)
375
throw lutok::api_error::from_stack(*this, "lua_gettable");
376
lua_remove(_pimpl->lua_state, -2);
377
}
378
379
380
/// Wrapper around lua_gettop.
381
///
382
/// \return The return value of lua_gettop.
383
int
384
lutok::state::get_top(void)
385
{
386
return lua_gettop(_pimpl->lua_state);
387
}
388
389
390
/// Wrapper around lua_insert.
391
///
392
/// \param index The second parameter to lua_insert.
393
void
394
lutok::state::insert(const int index)
395
{
396
lua_insert(_pimpl->lua_state, index);
397
}
398
399
400
/// Wrapper around lua_isboolean.
401
///
402
/// \param index The second parameter to lua_isboolean.
403
///
404
/// \return The return value of lua_isboolean.
405
bool
406
lutok::state::is_boolean(const int index)
407
{
408
return lua_isboolean(_pimpl->lua_state, index);
409
}
410
411
412
/// Wrapper around lua_isfunction.
413
///
414
/// \param index The second parameter to lua_isfunction.
415
///
416
/// \return The return value of lua_isfunction.
417
bool
418
lutok::state::is_function(const int index)
419
{
420
return lua_isfunction(_pimpl->lua_state, index);
421
}
422
423
424
/// Wrapper around lua_isnil.
425
///
426
/// \param index The second parameter to lua_isnil.
427
///
428
/// \return The return value of lua_isnil.
429
bool
430
lutok::state::is_nil(const int index)
431
{
432
return lua_isnil(_pimpl->lua_state, index);
433
}
434
435
436
/// Wrapper around lua_isnumber.
437
///
438
/// \param index The second parameter to lua_isnumber.
439
///
440
/// \return The return value of lua_isnumber.
441
bool
442
lutok::state::is_number(const int index)
443
{
444
return lua_isnumber(_pimpl->lua_state, index);
445
}
446
447
448
/// Wrapper around lua_isstring.
449
///
450
/// \param index The second parameter to lua_isstring.
451
///
452
/// \return The return value of lua_isstring.
453
bool
454
lutok::state::is_string(const int index)
455
{
456
return lua_isstring(_pimpl->lua_state, index);
457
}
458
459
460
/// Wrapper around lua_istable.
461
///
462
/// \param index The second parameter to lua_istable.
463
///
464
/// \return The return value of lua_istable.
465
bool
466
lutok::state::is_table(const int index)
467
{
468
return lua_istable(_pimpl->lua_state, index);
469
}
470
471
472
/// Wrapper around lua_isuserdata.
473
///
474
/// \param index The second parameter to lua_isuserdata.
475
///
476
/// \return The return value of lua_isuserdata.
477
bool
478
lutok::state::is_userdata(const int index)
479
{
480
return lua_isuserdata(_pimpl->lua_state, index);
481
}
482
483
484
/// Wrapper around luaL_loadfile.
485
///
486
/// \param file The second parameter to luaL_loadfile.
487
///
488
/// \throw api_error If luaL_loadfile returns an error.
489
/// \throw file_not_found_error If the file cannot be accessed.
490
///
491
/// \warning Terminates execution if there is not enough memory.
492
void
493
lutok::state::load_file(const std::string& file)
494
{
495
if (::access(file.c_str(), R_OK) == -1)
496
throw lutok::file_not_found_error(file);
497
if (luaL_loadfile(_pimpl->lua_state, file.c_str()) != 0)
498
throw lutok::api_error::from_stack(*this, "luaL_loadfile");
499
}
500
501
502
/// Wrapper around luaL_loadstring.
503
///
504
/// \param str The second parameter to luaL_loadstring.
505
///
506
/// \throw api_error If luaL_loadstring returns an error.
507
///
508
/// \warning Terminates execution if there is not enough memory.
509
void
510
lutok::state::load_string(const std::string& str)
511
{
512
if (luaL_loadstring(_pimpl->lua_state, str.c_str()) != 0)
513
throw lutok::api_error::from_stack(*this, "luaL_loadstring");
514
}
515
516
517
/// Wrapper around lua_newtable.
518
///
519
/// \warning Terminates execution if there is not enough memory.
520
void
521
lutok::state::new_table(void)
522
{
523
lua_newtable(_pimpl->lua_state);
524
}
525
526
527
/// Wrapper around lua_newuserdata.
528
///
529
/// This is internal. The public type-safe interface of this method should be
530
/// used instead.
531
///
532
/// \param size The second parameter to lua_newuserdata.
533
///
534
/// \return The return value of lua_newuserdata.
535
///
536
/// \warning Terminates execution if there is not enough memory.
537
void*
538
lutok::state::new_userdata_voidp(const size_t size)
539
{
540
return lua_newuserdata(_pimpl->lua_state, size);
541
}
542
543
544
/// Wrapper around lua_next.
545
///
546
/// \param index The second parameter to lua_next.
547
///
548
/// \return True if there are more elements to process; false otherwise.
549
///
550
/// \warning Terminates execution if there is not enough memory.
551
bool
552
lutok::state::next(const int index)
553
{
554
assert(lua_istable(_pimpl->lua_state, index));
555
assert(lua_gettop(_pimpl->lua_state) >= 1);
556
lua_pushcfunction(_pimpl->lua_state, protected_next);
557
lua_pushvalue(_pimpl->lua_state, index < 0 ? index - 1 : index);
558
lua_pushvalue(_pimpl->lua_state, -3);
559
if (lua_pcall(_pimpl->lua_state, 2, LUA_MULTRET, 0) != 0)
560
throw lutok::api_error::from_stack(*this, "lua_next");
561
const bool more = lua_toboolean(_pimpl->lua_state, -1);
562
lua_pop(_pimpl->lua_state, 1);
563
if (more)
564
lua_remove(_pimpl->lua_state, -3);
565
else
566
lua_pop(_pimpl->lua_state, 1);
567
return more;
568
}
569
570
571
/// Wrapper around luaL_openlibs.
572
///
573
/// \throw api_error If luaL_openlibs fails.
574
///
575
/// \warning Terminates execution if there is not enough memory.
576
void
577
lutok::state::open_all(void)
578
{
579
luaL_openlibs(_pimpl->lua_state);
580
}
581
582
583
/// Wrapper around luaopen_base.
584
///
585
/// \throw api_error If luaopen_base fails.
586
///
587
/// \warning Terminates execution if there is not enough memory.
588
void
589
lutok::state::open_base(void)
590
{
591
lua_pushcfunction(_pimpl->lua_state, luaopen_base);
592
if (lua_pcall(_pimpl->lua_state, 0, 0, 0) != 0)
593
throw lutok::api_error::from_stack(*this, "luaopen_base");
594
}
595
596
597
/// Wrapper around luaopen_string.
598
///
599
/// \throw api_error If luaopen_string fails.
600
///
601
/// \warning Terminates execution if there is not enough memory.
602
void
603
lutok::state::open_string(void)
604
{
605
#if LUA_VERSION_NUM >= 502
606
luaL_requiref(_pimpl->lua_state, LUA_STRLIBNAME, luaopen_string, 1);
607
lua_pop(_pimpl->lua_state, 1);
608
#else
609
lua_pushcfunction(_pimpl->lua_state, luaopen_string);
610
if (lua_pcall(_pimpl->lua_state, 0, 0, 0) != 0)
611
throw lutok::api_error::from_stack(*this, "luaopen_string");
612
#endif
613
}
614
615
616
/// Wrapper around luaopen_table.
617
///
618
/// \throw api_error If luaopen_table fails.
619
///
620
/// \warning Terminates execution if there is not enough memory.
621
void
622
lutok::state::open_table(void)
623
{
624
#if LUA_VERSION_NUM >= 502
625
luaL_requiref(_pimpl->lua_state, LUA_TABLIBNAME, luaopen_table, 1);
626
lua_pop(_pimpl->lua_state, 1);
627
#else
628
lua_pushcfunction(_pimpl->lua_state, luaopen_table);
629
if (lua_pcall(_pimpl->lua_state, 0, 0, 0) != 0)
630
throw lutok::api_error::from_stack(*this, "luaopen_table");
631
#endif
632
}
633
634
635
/// Wrapper around lua_pcall.
636
///
637
/// \param nargs The second parameter to lua_pcall.
638
/// \param nresults The third parameter to lua_pcall.
639
/// \param errfunc The fourth parameter to lua_pcall.
640
///
641
/// \throw api_error If lua_pcall returns an error.
642
void
643
lutok::state::pcall(const int nargs, const int nresults, const int errfunc)
644
{
645
if (lua_pcall(_pimpl->lua_state, nargs, nresults, errfunc) != 0)
646
throw lutok::api_error::from_stack(*this, "lua_pcall");
647
}
648
649
650
/// Wrapper around lua_pop.
651
///
652
/// \param count The second parameter to lua_pop.
653
void
654
lutok::state::pop(const int count)
655
{
656
assert(count <= lua_gettop(_pimpl->lua_state));
657
lua_pop(_pimpl->lua_state, count);
658
assert(lua_gettop(_pimpl->lua_state) >= 0);
659
}
660
661
662
/// Wrapper around lua_pushboolean.
663
///
664
/// \param value The second parameter to lua_pushboolean.
665
void
666
lutok::state::push_boolean(const bool value)
667
{
668
lua_pushboolean(_pimpl->lua_state, value ? 1 : 0);
669
}
670
671
672
/// Wrapper around lua_pushcclosure.
673
///
674
/// This is not a pure wrapper around lua_pushcclosure because this has to do
675
/// extra magic to allow passing C++ functions instead of plain C functions.
676
///
677
/// \param function The C++ function to be pushed as a closure.
678
/// \param nvalues The number of upvalues that the function receives.
679
void
680
lutok::state::push_cxx_closure(cxx_function function, const int nvalues)
681
{
682
cxx_function *data = static_cast< cxx_function* >(
683
lua_newuserdata(_pimpl->lua_state, sizeof(cxx_function)));
684
*data = function;
685
lua_pushcclosure(_pimpl->lua_state, cxx_closure_trampoline, nvalues + 1);
686
}
687
688
689
/// Wrapper around lua_pushcfunction.
690
///
691
/// This is not a pure wrapper around lua_pushcfunction because this has to do
692
/// extra magic to allow passing C++ functions instead of plain C functions.
693
///
694
/// \param function The C++ function to be pushed.
695
void
696
lutok::state::push_cxx_function(cxx_function function)
697
{
698
cxx_function *data = static_cast< cxx_function* >(
699
lua_newuserdata(_pimpl->lua_state, sizeof(cxx_function)));
700
*data = function;
701
lua_pushcclosure(_pimpl->lua_state, cxx_function_trampoline, 1);
702
}
703
704
705
/// Wrapper around lua_pushinteger.
706
///
707
/// \param value The second parameter to lua_pushinteger.
708
void
709
lutok::state::push_integer(const int value)
710
{
711
lua_pushinteger(_pimpl->lua_state, value);
712
}
713
714
715
/// Wrapper around lua_pushnil.
716
void
717
lutok::state::push_nil(void)
718
{
719
lua_pushnil(_pimpl->lua_state);
720
}
721
722
723
/// Wrapper around lua_pushstring.
724
///
725
/// \param str The second parameter to lua_pushstring.
726
///
727
/// \warning Terminates execution if there is not enough memory.
728
void
729
lutok::state::push_string(const std::string& str)
730
{
731
lua_pushstring(_pimpl->lua_state, str.c_str());
732
}
733
734
735
/// Wrapper around lua_pushvalue.
736
///
737
/// \param index The second parameter to lua_pushvalue.
738
void
739
lutok::state::push_value(const int index)
740
{
741
lua_pushvalue(_pimpl->lua_state, index);
742
}
743
744
745
/// Wrapper around lua_rawget.
746
///
747
/// \param index The second parameter to lua_rawget.
748
void
749
lutok::state::raw_get(const int index)
750
{
751
lua_rawget(_pimpl->lua_state, index);
752
}
753
754
755
/// Wrapper around lua_rawset.
756
///
757
/// \param index The second parameter to lua_rawset.
758
///
759
/// \warning Terminates execution if there is not enough memory to manipulate
760
/// the Lua stack.
761
void
762
lutok::state::raw_set(const int index)
763
{
764
lua_rawset(_pimpl->lua_state, index);
765
}
766
767
768
/// Wrapper around lua_setglobal.
769
///
770
/// \param name The second parameter to lua_setglobal.
771
///
772
/// \throw api_error If lua_setglobal fails.
773
///
774
/// \warning Terminates execution if there is not enough memory to manipulate
775
/// the Lua stack.
776
void
777
lutok::state::set_global(const std::string& name)
778
{
779
lua_pushcfunction(_pimpl->lua_state, protected_setglobal);
780
lua_pushstring(_pimpl->lua_state, name.c_str());
781
lua_pushvalue(_pimpl->lua_state, -3);
782
if (lua_pcall(_pimpl->lua_state, 2, 0, 0) != 0)
783
throw lutok::api_error::from_stack(*this, "lua_setglobal");
784
lua_pop(_pimpl->lua_state, 1);
785
}
786
787
788
/// Wrapper around lua_setmetatable.
789
///
790
/// \param index The second parameter to lua_setmetatable.
791
void
792
lutok::state::set_metatable(const int index)
793
{
794
lua_setmetatable(_pimpl->lua_state, index);
795
}
796
797
798
/// Wrapper around lua_settable.
799
///
800
/// \param index The second parameter to lua_settable.
801
///
802
/// \throw api_error If lua_settable fails.
803
///
804
/// \warning Terminates execution if there is not enough memory to manipulate
805
/// the Lua stack.
806
void
807
lutok::state::set_table(const int index)
808
{
809
lua_pushcfunction(_pimpl->lua_state, protected_settable);
810
lua_pushvalue(_pimpl->lua_state, index < 0 ? index - 1 : index);
811
lua_pushvalue(_pimpl->lua_state, -4);
812
lua_pushvalue(_pimpl->lua_state, -4);
813
if (lua_pcall(_pimpl->lua_state, 3, 0, 0) != 0)
814
throw lutok::api_error::from_stack(*this, "lua_settable");
815
lua_pop(_pimpl->lua_state, 2);
816
}
817
818
819
/// Wrapper around lua_toboolean.
820
///
821
/// \param index The second parameter to lua_toboolean.
822
///
823
/// \return The return value of lua_toboolean.
824
bool
825
lutok::state::to_boolean(const int index)
826
{
827
assert(is_boolean(index));
828
return lua_toboolean(_pimpl->lua_state, index);
829
}
830
831
832
/// Wrapper around lua_tointeger.
833
///
834
/// \param index The second parameter to lua_tointeger.
835
///
836
/// \return The return value of lua_tointeger.
837
long
838
lutok::state::to_integer(const int index)
839
{
840
assert(is_number(index));
841
return lua_tointeger(_pimpl->lua_state, index);
842
}
843
844
845
/// Wrapper around lua_touserdata.
846
///
847
/// This is internal. The public type-safe interface of this method should be
848
/// used instead.
849
///
850
/// \param index The second parameter to lua_touserdata.
851
///
852
/// \return The return value of lua_touserdata.
853
///
854
/// \warning Terminates execution if there is not enough memory.
855
void*
856
lutok::state::to_userdata_voidp(const int index)
857
{
858
return lua_touserdata(_pimpl->lua_state, index);
859
}
860
861
862
863
/// Wrapper around lua_tostring.
864
///
865
/// \param index The second parameter to lua_tostring.
866
///
867
/// \return The return value of lua_tostring.
868
///
869
/// \warning Terminates execution if there is not enough memory.
870
std::string
871
lutok::state::to_string(const int index)
872
{
873
assert(is_string(index));
874
const char *raw_string = lua_tostring(_pimpl->lua_state, index);
875
// Note that the creation of a string object below (explicit for clarity)
876
// implies that the raw string is duplicated and, henceforth, the string is
877
// safe even if the corresponding element is popped from the Lua stack.
878
return std::string(raw_string);
879
}
880
881
882
/// Wrapper around lua_upvalueindex.
883
///
884
/// \param index The first parameter to lua_upvalueindex.
885
///
886
/// \return The return value of lua_upvalueindex.
887
int
888
lutok::state::upvalue_index(const int index)
889
{
890
return lua_upvalueindex(index);
891
}
892
893
894
/// Gets the internal lua_State object.
895
///
896
/// \return The raw Lua state. This is returned as a void pointer to prevent
897
/// including the lua.hpp header file from our public interface. The only way
898
/// to call this method is by using the c_gate module, and c_gate takes care of
899
/// casting this object to the appropriate type.
900
void*
901
lutok::state::raw_state(void)
902
{
903
return _pimpl->lua_state;
904
}
905
906