Skip to content
This repository was archived by the owner on Dec 29, 2024. It is now read-only.

Commit 9a859ac

Browse files
authored
Add UTF8 support (#162)
1 parent ae3c36e commit 9a859ac

1 file changed

Lines changed: 69 additions & 54 deletions

File tree

lua.cpp

Lines changed: 69 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Lua::Lua(){
2828
state = luaL_newstate();
2929
// threaded is false by default
3030
threaded = false;
31-
31+
3232
// loading base libs
3333
luaL_requiref(state, "", luaopen_base, 1);
3434
lua_pop(state, 1);
@@ -38,7 +38,7 @@ Lua::Lua(){
3838
lua_pop(state, 1);
3939
luaL_requiref(state, LUA_MATHLIBNAME, luaopen_math, 1);
4040
lua_pop(state, 1);
41-
41+
4242
lua_sethook(state, &LineHook, LUA_MASKLINE, 0);
4343
lua_register(state, "print", luaPrint);
4444

@@ -54,15 +54,15 @@ Lua::Lua(){
5454

5555
// Exposing basic types constructors
5656
exposeConstructors();
57-
57+
5858
}
5959

6060
Lua::~Lua(){
6161
// Warning users about object destruction if code is currently being executed see https://github.com/Trey2k/lua/issues/9
6262
if (executing){
6363
print_line("WARNING! Lua object is being destroyed while code is currently being executed.");
6464
}
65-
65+
6666
// Destroying lua state instance
6767
lua_close(state);
6868
}
@@ -83,12 +83,14 @@ void Lua::_bind_methods(){
8383

8484
// expose a GDScript function to lua
8585
void Lua::exposeFunction(Object *instance, String function, String name){
86-
86+
8787
// Createing lamda function so we can capture the object instanse and call the GDScript method. Or in theory other scripting languages?
8888
auto f = [](lua_State* L) -> int{
8989
const Object *instance2 = (const Object*) lua_topointer(L, lua_upvalueindex(1));
9090
class Lua *obj = (class Lua*) lua_topointer(L, lua_upvalueindex(2));
91-
const char *function2 = lua_tostring(L, lua_upvalueindex(3));
91+
92+
String function2;
93+
function2.parse_utf8(lua_tostring(L, lua_upvalueindex(3)));
9294

9395
Variant arg1 = obj->getVariant(1);
9496
Variant arg2 = obj->getVariant(2);
@@ -112,21 +114,21 @@ void Lua::exposeFunction(Object *instance, String function, String name){
112114
lua_pushlightuserdata(state, this);
113115

114116
// Pushing the script function name string to the stack to br retrived when called
115-
lua_pushstring(state, function.ascii().get_data());
117+
lua_pushstring(state, function.utf8().get_data());
116118

117119
// Pushing the actual lambda function to the stack
118120
lua_pushcclosure(state, f, 3);
119121
// Setting the global name for the function in lua
120-
lua_setglobal(state, name.ascii().get_data());
121-
122+
lua_setglobal(state, name.utf8().get_data());
123+
122124
}
123125

124126
// call a Lua function from GDScript
125127
Variant Lua::callFunction( String function_name, Array args , bool protected_call , Object* callback_caller , String callback ) {
126128
Variant toReturn;
127129
int stack_size = lua_gettop(state);
128130
// put global function name on stack
129-
lua_getglobal(state, function_name.ascii().get_data() );
131+
lua_getglobal(state, function_name.utf8().get_data() );
130132

131133
// push args
132134
for (int i = 0; i < args.size(); ++i) {
@@ -141,12 +143,14 @@ Variant Lua::callFunction( String function_name, Array args , bool protected_cal
141143
if( callback_caller == nullptr || callback == String() ){
142144
print_error( vformat("Error during \"Lua::callFunction\" on Lua function \"%s\": ",function_name) );
143145
handleError( state , ret );
144-
}
145-
146+
}
147+
146148
// Custom error handling:
147149
else {
148150
ScriptInstance *scriptInstance = callback_caller->get_script_instance();
149-
scriptInstance->call(callback, String(lua_tostring(state,-1)) );
151+
String errorHandler;
152+
errorHandler.parse_utf8(lua_tostring(state,-1));
153+
scriptInstance->call(callback, errorHandler);
150154
}
151155
}
152156
toReturn = getVariant(1);
@@ -161,7 +165,7 @@ Variant Lua::callFunction( String function_name, Array args , bool protected_cal
161165
}
162166

163167
bool Lua::luaFunctionExists(String function_name){
164-
int type = lua_getglobal( state , function_name.ascii().get_data() );
168+
int type = lua_getglobal( state , function_name.utf8().get_data() );
165169
lua_pop(state,1);
166170
return type == LUA_TFUNCTION;
167171
}
@@ -196,38 +200,40 @@ void Lua::LineHook(lua_State *L, lua_Debug *ar){
196200
}
197201

198202
// Run lua string in a thread if threading is enabled
199-
void Lua::doString( String code, bool protected_call , Object* callback_caller , String callback ){
203+
void Lua::doString(String code, bool protected_call, Object* callback_caller, String callback){
200204
if(threaded){
201-
std::thread(runLua, state , code , protected_call , callback_caller , callback , &executing ).detach();
205+
std::thread(runLua, state, code, protected_call, callback_caller, callback, &executing).detach();
202206
}else{
203-
runLua( state , code , protected_call , callback_caller , callback , &executing );
207+
runLua(state, code, protected_call, callback_caller, callback, &executing);
204208
}
205209
}
206210

207211
// Execute a lua script string and , if protected_call, call the passed callBack function with the error as the aurgument if an error occurees
208-
void Lua::runLua( lua_State *L , String code, bool protected_call , Object* callback_caller , String callback, bool *executing ){
212+
void Lua::runLua(lua_State *L, String code, bool protected_call, Object* callback_caller, String callback, bool *executing){
209213
*executing = true;
210214
if( protected_call ){
211-
212-
int ret = luaL_dostring( L , code.ascii().get_data() );
215+
216+
int ret = luaL_dostring(L , code.utf8().get_data());
213217
if( ret != LUA_OK ){
214218

215219
// Default error handling:
216220
if( callback_caller == nullptr || callback == String() ){
217221
handleError( L , ret );
218-
}
219-
222+
}
223+
220224
// Custom error handling:
221225
else {
222226
ScriptInstance *scriptInstance = callback_caller->get_script_instance();
223-
scriptInstance->call(callback, String(lua_tostring(L,-1)) );
227+
String errorHandler;
228+
errorHandler.parse_utf8(lua_tostring(L,-1));
229+
scriptInstance->call(callback, errorHandler);
224230
}
225231
}
226-
}
232+
}
227233

228234
// Call not protected (crashes and exit the program if error!)
229235
else {
230-
luaL_loadstring(L, code.ascii().get_data() ) ;
236+
luaL_loadstring(L, code.utf8().get_data() ) ;
231237
lua_call(L, 0 /* nargs */ , 0 /* nresults */ ) ;
232238
}
233239

@@ -244,8 +250,7 @@ bool Lua::pushVariant(Variant var) {
244250
lua_pushnil(state);
245251
break;
246252
case Variant::Type::STRING:
247-
str = (var.operator String().c_str());
248-
lua_pushstring(state, std::string( str.begin(), str.end() ).c_str());
253+
lua_pushstring(state, (var.operator String()).utf8().get_data());
249254
break;
250255
case Variant::Type::INT:
251256
lua_pushinteger(state, (int64_t)var);
@@ -262,7 +267,7 @@ bool Lua::pushVariant(Variant var) {
262267
case Variant::Type::POOL_REAL_ARRAY:
263268
case Variant::Type::POOL_VECTOR2_ARRAY:
264269
case Variant::Type::POOL_VECTOR3_ARRAY:
265-
case Variant::Type::POOL_COLOR_ARRAY:
270+
case Variant::Type::POOL_COLOR_ARRAY:
266271
case Variant::Type::ARRAY: {
267272
Array array = var.operator Array();
268273
lua_newtable(state);
@@ -289,19 +294,19 @@ bool Lua::pushVariant(Variant var) {
289294
void* userdata = (Variant*)lua_newuserdata( state , sizeof(Variant) );
290295
memcpy( userdata , (void*)&var , sizeof(Variant) );
291296
luaL_setmetatable(state,"mt_Vector2");
292-
break;
293-
}
297+
break;
298+
}
294299
case Variant::Type::VECTOR3: {
295300
void* userdata = (Variant*)lua_newuserdata( state , sizeof(Variant) );
296301
memcpy( userdata , (void*)&var , sizeof(Variant) );
297302
luaL_setmetatable(state,"mt_Vector3");
298-
break;
303+
break;
299304
}
300305
case Variant::Type::COLOR: {
301306
void* userdata = (Variant*)lua_newuserdata( state , sizeof(Variant) );
302307
memcpy( userdata , (void*)&var , sizeof(Variant) );
303308
luaL_setmetatable(state,"mt_Color");
304-
break;
309+
break;
305310
}
306311
default:
307312
print_error( vformat("Can't pass Variants of type \"%s\" to Lua." , Variant::get_type_name( var.get_type() ) ) );
@@ -314,16 +319,15 @@ bool Lua::pushVariant(Variant var) {
314319
// Call pushVariant() and set it to a global name
315320
bool Lua::pushGlobalVariant(Variant var, String name) {
316321
if (pushVariant(var)) {
317-
std::wstring str = name.c_str();
318-
lua_setglobal(state,std::string( str.begin(), str.end() ).c_str());
322+
lua_setglobal(state, name.utf8().get_data());
319323
return true;
320324
}
321325
return false;
322326
}
323327

324328
// Pull a global variant from Lua to GDScript
325329
Variant Lua::pullVariant(String name){
326-
int type = lua_getglobal(state, name.ascii().get_data());
330+
int type = lua_getglobal(state, name.utf8().get_data());
327331
Variant val = getVariant(1);
328332
lua_pop(state, 1);
329333
return val;
@@ -333,9 +337,12 @@ Variant Lua::getVariant(int index) {
333337
Variant result;
334338
int type = lua_type(state, index);
335339
switch (type) {
336-
case LUA_TSTRING:
337-
result = lua_tostring(state, index);
340+
case LUA_TSTRING:{
341+
String utf8_str;
342+
utf8_str.parse_utf8(lua_tostring(state, index));
343+
result = utf8_str;
338344
break;
345+
}
339346
case LUA_TNUMBER:
340347
result = lua_tonumber(state, index);
341348
break;
@@ -365,8 +372,8 @@ Variant Lua::getVariant(int index) {
365372
}
366373

367374

368-
void Lua::exposeConstructors( ){
369-
375+
void Lua::exposeConstructors(){
376+
370377
lua_pushcfunction(state,LUA_LAMBDA_TEMPLATE({
371378
int argc = lua_gettop(inner_state);
372379
if( argc == 0 ){
@@ -416,7 +423,7 @@ void Lua::createVector2Metatable( ){
416423
// We can't use arg1 here because we need to reference the userdata
417424
((Variant*)lua_touserdata(inner_state,1))->set( arg2 , arg3 );
418425
return 0;
419-
});
426+
});
420427

421428
LUA_METAMETHOD_TEMPLATE( state , -1 , "__add" , {
422429
lua->pushVariant( arg1.operator Vector2() + arg2.operator Vector2() );
@@ -473,7 +480,7 @@ void Lua::createVector3Metatable( ){
473480
// We can't use arg1 here because we need to reference the userdata
474481
((Variant*)lua_touserdata(inner_state,1))->set( arg2 , arg3 );
475482
return 0;
476-
});
483+
});
477484

478485
LUA_METAMETHOD_TEMPLATE( state , -1 , "__add" , {
479486
lua->pushVariant( arg1.operator Vector3() + arg2.operator Vector3() );
@@ -530,7 +537,7 @@ void Lua::createColorMetatable( ){
530537
// We can't use arg1 here because we need to reference the userdata
531538
((Variant*)lua_touserdata(inner_state,1))->set( arg2 , arg3 );
532539
return 0;
533-
});
540+
});
534541

535542
LUA_METAMETHOD_TEMPLATE( state , -1 , "__add" , {
536543
lua->pushVariant( arg1.operator Color() + arg2.operator Color() );
@@ -574,7 +581,7 @@ void Lua::createColorMetatable( ){
574581
}
575582

576583
// Assumes there is a error in the top of the stack. Pops it.
577-
void Lua::handleError( lua_State* L , int lua_error ){
584+
void Lua::handleError(lua_State* L, int lua_error){
578585
String msg;
579586
switch( lua_error ){
580587
case LUA_ERRRUN:
@@ -588,36 +595,44 @@ void Lua::handleError( lua_State* L , int lua_error ){
588595
break;
589596
default: break;
590597
}
591-
msg += lua_tostring(L,-1);
592-
print_error( msg );
593-
lua_pop(L,1);
598+
String utf8_str;
599+
utf8_str.parse_utf8(lua_tostring(L, -1));
600+
msg += utf8_str;
601+
print_error(msg);
602+
lua_pop(L, 1);
594603
}
595604

596605
// Lua functions
597606
// Change lua's print function to print to the Godot console by default
598607
int Lua::luaPrint(lua_State* state)
599608
{
600609

601-
int args = lua_gettop(state);
602-
String final_string;
603-
for ( int n=1; n<=args; ++n) {
610+
int args = lua_gettop(state);
611+
String final_string;
612+
for (int n = 1; n <= args; ++n) {
604613
String it_string;
605-
606-
switch( lua_type(state,n) ){
614+
615+
switch(lua_type(state, n)){
607616
case LUA_TUSERDATA:{
608617
Variant var = *(Variant*) lua_touserdata(state,n);
609618
it_string = var.operator String();
610619
break;
611620
}
621+
case LUA_TBOOLEAN: {
622+
it_string = lua_toboolean(state, n) ? "true" : "false";
623+
break;
624+
}
612625
default:{
613-
it_string = lua_tostring(state, n);
626+
it_string.parse_utf8(lua_tostring(state, n));
614627
break;
615628
}
616629
}
617630

618631
final_string += it_string;
619-
if( n < args ) final_string += ", ";
620-
}
632+
if (n < args) {
633+
final_string += ", ";
634+
}
635+
}
621636

622637
print_line( final_string );
623638

0 commit comments

Comments
 (0)