2 Cafu Engine, http://www.cafu.de/
3 Copyright (c) Carsten Fuchs and other contributors.
4 This project is licensed under the terms of the MIT license.
7 #include "VarVisitorsLua.hpp"
18 using namespace cf::TypeSys
;
21 /***************************/
22 /*** VarVisitorGetToLuaT ***/
23 /***************************/
25 VarVisitorGetToLuaT::VarVisitorGetToLuaT(lua_State
* LuaState
)
26 : m_LuaState(LuaState
),
32 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarT
<float>& Var
)
34 lua_pushnumber(m_LuaState
, Var
.Get());
39 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarT
<double>& Var
)
41 lua_pushnumber(m_LuaState
, Var
.Get());
46 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarT
<int>& Var
)
48 lua_pushinteger(m_LuaState
, Var
.Get());
53 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarT
<unsigned int>& Var
)
55 lua_pushinteger(m_LuaState
, Var
.Get());
60 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarT
<uint16_t>& Var
)
62 lua_pushinteger(m_LuaState
, Var
.Get());
67 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarT
<uint8_t>& Var
)
69 lua_pushinteger(m_LuaState
, Var
.Get());
74 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarT
<bool>& Var
)
76 lua_pushboolean(m_LuaState
, Var
.Get());
81 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarT
<std::string
>& Var
)
83 lua_pushstring(m_LuaState
, Var
.Get().c_str());
88 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarT
<Vector2fT
>& Var
)
90 lua_pushnumber(m_LuaState
, Var
.Get().x
); m_NumResults
++;
91 lua_pushnumber(m_LuaState
, Var
.Get().y
); m_NumResults
++;
95 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarT
<Vector3fT
>& Var
)
97 lua_pushnumber(m_LuaState
, Var
.Get().x
); m_NumResults
++;
98 lua_pushnumber(m_LuaState
, Var
.Get().y
); m_NumResults
++;
99 lua_pushnumber(m_LuaState
, Var
.Get().z
); m_NumResults
++;
103 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarT
<Vector3dT
>& Var
)
105 lua_pushnumber(m_LuaState
, Var
.Get().x
); m_NumResults
++;
106 lua_pushnumber(m_LuaState
, Var
.Get().y
); m_NumResults
++;
107 lua_pushnumber(m_LuaState
, Var
.Get().z
); m_NumResults
++;
111 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarT
<BoundingBox3dT
>& Var
)
113 lua_pushnumber(m_LuaState
, Var
.Get().Min
.x
); m_NumResults
++;
114 lua_pushnumber(m_LuaState
, Var
.Get().Min
.y
); m_NumResults
++;
115 lua_pushnumber(m_LuaState
, Var
.Get().Min
.z
); m_NumResults
++;
117 lua_pushnumber(m_LuaState
, Var
.Get().Max
.x
); m_NumResults
++;
118 lua_pushnumber(m_LuaState
, Var
.Get().Max
.y
); m_NumResults
++;
119 lua_pushnumber(m_LuaState
, Var
.Get().Max
.z
); m_NumResults
++;
123 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarArrayT
<uint32_t>& Var
)
125 lua_newtable(m_LuaState
);
128 for (unsigned int i
= 0; i
< Var
.Size(); i
++)
130 lua_pushinteger(m_LuaState
, Var
[i
]);
131 lua_rawseti(m_LuaState
, -2, i
+ 1); // Lua array numbering starts per convention at 1.
136 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarArrayT
<uint16_t>& Var
)
138 lua_newtable(m_LuaState
);
141 for (unsigned int i
= 0; i
< Var
.Size(); i
++)
143 lua_pushinteger(m_LuaState
, Var
[i
]);
144 lua_rawseti(m_LuaState
, -2, i
+ 1); // Lua array numbering starts per convention at 1.
149 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarArrayT
<uint8_t>& Var
)
151 lua_newtable(m_LuaState
);
154 for (unsigned int i
= 0; i
< Var
.Size(); i
++)
156 lua_pushinteger(m_LuaState
, Var
[i
]);
157 lua_rawseti(m_LuaState
, -2, i
+ 1); // Lua array numbering starts per convention at 1.
162 void VarVisitorGetToLuaT::visit(const cf::TypeSys::VarArrayT
<std::string
>& Var
)
164 lua_newtable(m_LuaState
);
167 for (unsigned int i
= 0; i
< Var
.Size(); i
++)
169 lua_pushstring(m_LuaState
, Var
[i
].c_str());
170 lua_rawseti(m_LuaState
, -2, i
+ 1); // Lua array numbering starts per convention at 1.
175 /*****************************/
176 /*** VarVisitorSetFromLuaT ***/
177 /*****************************/
179 VarVisitorSetFromLuaT::VarVisitorSetFromLuaT(lua_State
* LuaState
)
180 : m_LuaState(LuaState
)
185 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarT
<float>& Var
)
187 Var
.Set(float(luaL_checknumber(m_LuaState
, -1)));
191 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarT
<double>& Var
)
193 Var
.Set(luaL_checknumber(m_LuaState
, -1));
197 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarT
<int>& Var
)
199 Var
.Set(luaL_checkint(m_LuaState
, -1));
203 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarT
<unsigned int>& Var
)
205 Var
.Set(luaL_checkint(m_LuaState
, -1));
209 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarT
<uint16_t>& Var
)
211 Var
.Set(luaL_checkint(m_LuaState
, -1));
215 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarT
<uint8_t>& Var
)
217 Var
.Set(luaL_checkint(m_LuaState
, -1));
221 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarT
<bool>& Var
)
223 // Also treat the number 0 as false, not just "false" and "nil".
224 if (lua_isnumber(m_LuaState
, -1))
225 Var
.Set(lua_tonumber(m_LuaState
, -1) != 0.0);
227 Var
.Set(lua_toboolean(m_LuaState
, -1) != 0);
231 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarT
<std::string
>& Var
)
233 Var
.Set(luaL_checkstring(m_LuaState
, -1));
237 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarT
<Vector2fT
>& Var
)
241 if (lua_istable(m_LuaState
, -1))
243 lua_rawgeti(m_LuaState
, -1, 1); v
.x
= float(lua_tonumber(m_LuaState
, -1)); lua_pop(m_LuaState
, 1);
244 lua_rawgeti(m_LuaState
, -1, 2); v
.y
= float(lua_tonumber(m_LuaState
, -1)); lua_pop(m_LuaState
, 1);
248 v
.x
= float(luaL_checknumber(m_LuaState
, -2));
249 v
.y
= float(luaL_checknumber(m_LuaState
, -1));
256 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarT
<Vector3fT
>& Var
)
260 if (lua_istable(m_LuaState
, -1))
262 lua_rawgeti(m_LuaState
, -1, 1); v
.x
= float(lua_tonumber(m_LuaState
, -1)); lua_pop(m_LuaState
, 1);
263 lua_rawgeti(m_LuaState
, -1, 2); v
.y
= float(lua_tonumber(m_LuaState
, -1)); lua_pop(m_LuaState
, 1);
264 lua_rawgeti(m_LuaState
, -1, 3); v
.z
= float(lua_tonumber(m_LuaState
, -1)); lua_pop(m_LuaState
, 1);
268 v
.x
= float(luaL_checknumber(m_LuaState
, -3));
269 v
.y
= float(luaL_checknumber(m_LuaState
, -2));
270 v
.z
= float(luaL_checknumber(m_LuaState
, -1));
277 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarT
<Vector3dT
>& Var
)
281 if (lua_istable(m_LuaState
, -1))
283 lua_rawgeti(m_LuaState
, -1, 1); v
.x
= lua_tonumber(m_LuaState
, -1); lua_pop(m_LuaState
, 1);
284 lua_rawgeti(m_LuaState
, -1, 2); v
.y
= lua_tonumber(m_LuaState
, -1); lua_pop(m_LuaState
, 1);
285 lua_rawgeti(m_LuaState
, -1, 3); v
.z
= lua_tonumber(m_LuaState
, -1); lua_pop(m_LuaState
, 1);
289 v
.x
= luaL_checknumber(m_LuaState
, -3);
290 v
.y
= luaL_checknumber(m_LuaState
, -2);
291 v
.z
= luaL_checknumber(m_LuaState
, -1);
298 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarT
<BoundingBox3dT
>& Var
)
302 BB
.Min
.x
= luaL_checknumber(m_LuaState
, -6);
303 BB
.Min
.y
= luaL_checknumber(m_LuaState
, -5);
304 BB
.Min
.z
= luaL_checknumber(m_LuaState
, -4);
306 BB
.Max
.x
= luaL_checknumber(m_LuaState
, -3);
307 BB
.Max
.y
= luaL_checknumber(m_LuaState
, -2);
308 BB
.Max
.z
= luaL_checknumber(m_LuaState
, -1);
314 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarArrayT
<uint32_t>& Var
)
318 if (lua_istable(m_LuaState
, -1))
320 const int Num
= int(lua_rawlen(m_LuaState
, -1));
322 for (int i
= 1; i
<= Num
; i
++)
324 lua_rawgeti(m_LuaState
, -1, i
);
325 Var
.PushBack(lua_tointeger(m_LuaState
, -1));
326 lua_pop(m_LuaState
, 1);
331 // Stack index 1 has the "this" object,
332 // stack index 2 has the variable name.
333 for (int i
= 3; i
<= lua_gettop(m_LuaState
); i
++)
334 Var
.PushBack(lua_tointeger(m_LuaState
, i
));
339 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarArrayT
<uint16_t>& Var
)
343 if (lua_istable(m_LuaState
, -1))
345 const int Num
= int(lua_rawlen(m_LuaState
, -1));
347 for (int i
= 1; i
<= Num
; i
++)
349 lua_rawgeti(m_LuaState
, -1, i
);
350 Var
.PushBack(lua_tointeger(m_LuaState
, -1));
351 lua_pop(m_LuaState
, 1);
356 // Stack index 1 has the "this" object,
357 // stack index 2 has the variable name.
358 for (int i
= 3; i
<= lua_gettop(m_LuaState
); i
++)
359 Var
.PushBack(lua_tointeger(m_LuaState
, i
));
364 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarArrayT
<uint8_t>& Var
)
368 if (lua_istable(m_LuaState
, -1))
370 const int Num
= int(lua_rawlen(m_LuaState
, -1));
372 for (int i
= 1; i
<= Num
; i
++)
374 lua_rawgeti(m_LuaState
, -1, i
);
375 Var
.PushBack(lua_tointeger(m_LuaState
, -1));
376 lua_pop(m_LuaState
, 1);
381 // Stack index 1 has the "this" object,
382 // stack index 2 has the variable name.
383 for (int i
= 3; i
<= lua_gettop(m_LuaState
); i
++)
384 Var
.PushBack(lua_tointeger(m_LuaState
, i
));
389 void VarVisitorSetFromLuaT::visit(cf::TypeSys::VarArrayT
<std::string
>& Var
)
393 if (lua_istable(m_LuaState
, -1))
395 const int Num
= int(lua_rawlen(m_LuaState
, -1));
397 for (int i
= 1; i
<= Num
; i
++)
399 lua_rawgeti(m_LuaState
, -1, i
);
400 const char* s
= lua_tostring(m_LuaState
, -1);
401 Var
.PushBack(s
? s
: "NULL");
402 lua_pop(m_LuaState
, 1);
407 // Stack index 1 has the "this" object,
408 // stack index 2 has the variable name.
409 for (int i
= 3; i
<= lua_gettop(m_LuaState
); i
++)
411 const char* s
= lua_tostring(m_LuaState
, i
);
412 Var
.PushBack(s
? s
: "NULL");
418 /***************************/
419 /*** VarVisitorSetFloatT ***/
420 /***************************/
422 VarVisitorSetFloatT::VarVisitorSetFloatT(unsigned int Suffix
, float Value
)
429 void VarVisitorSetFloatT::visit(cf::TypeSys::VarT
<float>& Var
)
435 void VarVisitorSetFloatT::visit(cf::TypeSys::VarT
<Vector2fT
>& Var
)
437 Vector2fT v
= Var
.Get();
439 v
[m_Suffix
% 2] = m_Value
;
445 void VarVisitorSetFloatT::visit(cf::TypeSys::VarT
<Vector3fT
>& Var
)
447 Vector3fT v
= Var
.Get();
449 v
[m_Suffix
% 3] = m_Value
;
455 void VarVisitorSetFloatT::visit(cf::TypeSys::VarT
<double>& Var
) { }
456 void VarVisitorSetFloatT::visit(cf::TypeSys::VarT
<int>& Var
) { }
457 void VarVisitorSetFloatT::visit(cf::TypeSys::VarT
<unsigned int>& Var
) { }
458 void VarVisitorSetFloatT::visit(cf::TypeSys::VarT
<uint16_t>& Var
) { }
459 void VarVisitorSetFloatT::visit(cf::TypeSys::VarT
<uint8_t>& Var
) { }
460 void VarVisitorSetFloatT::visit(cf::TypeSys::VarT
<bool>& Var
) { }
461 void VarVisitorSetFloatT::visit(cf::TypeSys::VarT
<std::string
>& Var
) { }
462 void VarVisitorSetFloatT::visit(cf::TypeSys::VarT
<Vector3dT
>& Var
) { }
463 void VarVisitorSetFloatT::visit(cf::TypeSys::VarT
<BoundingBox3dT
>& Var
) { }
464 void VarVisitorSetFloatT::visit(cf::TypeSys::VarArrayT
<uint32_t>& Var
) { }
465 void VarVisitorSetFloatT::visit(cf::TypeSys::VarArrayT
<uint16_t>& Var
) { }
466 void VarVisitorSetFloatT::visit(cf::TypeSys::VarArrayT
<uint8_t>& Var
) { }
467 void VarVisitorSetFloatT::visit(cf::TypeSys::VarArrayT
<std::string
>& Var
) { }
470 /****************************/
471 /*** VarVisitorToLuaCodeT ***/
472 /****************************/
476 /// This function serializes a given float f1 to a string s, such that:
477 /// - s is minimal (uses the least number of decimal digits required),
478 /// - unserializing s back to a float f2 yields f1 == f2.
479 /// See my post "float to string to float, with first float == second float"
480 /// to comp.lang.c++ on 2009-10-06 for additional details.
481 template<class T
> std::string
serialize(const T f1
)
483 // Make sure that if f1 is -0, "0" instead of "-0" is returned.
484 if (f1
== 0.0f
) return "0";
486 // From MSDN documentation: "digits10 returns the number of decimal digits that the type can represent without loss of precision."
487 // For floats, that's usually 6, for doubles, that's usually 15. However, we want to use the number of *significant* decimal digits here,
488 // that is, max_digits10. See http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2006/n2005.pdf for details.
489 const unsigned int DIGITS10
= std::numeric_limits
<T
>::digits10
;
490 const unsigned int MAX_DIGITS10
= DIGITS10
+ 3;
495 for (prec
= DIGITS10
; prec
<= MAX_DIGITS10
; prec
++)
497 std::stringstream ss
;
504 #if defined(_MSC_VER) && (_MSC_VER <= 1900) // 1900 == Visual C++ 14.0 (2015)
505 // There is a bug in Microsoft's iostream implementation up to Visual C++ 2015,
506 // see http://trac.cafu.de/ticket/150 for details.
507 const T f2
= T(atof(s
.c_str()));
516 assert(prec
<= MAX_DIGITS10
);
522 VarVisitorToLuaCodeT::VarVisitorToLuaCodeT(std::ostream
& Out
)
528 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarT
<float>& Var
)
530 m_Out
<< serialize(Var
.Get());
534 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarT
<double>& Var
)
536 m_Out
<< serialize(Var
.Get());
540 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarT
<int>& Var
)
546 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarT
<unsigned int>& Var
)
552 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarT
<uint16_t>& Var
)
558 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarT
<uint8_t>& Var
)
560 m_Out
<< uint16_t(Var
.Get()); // Write numbers, not characters.
564 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarT
<bool>& Var
)
566 m_Out
<< (Var
.Get() ? "true" : "false");
570 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarT
<std::string
>& Var
)
572 WriteString(Var
.Get());
576 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarT
<Vector2fT
>& Var
)
578 m_Out
<< serialize(Var
.Get().x
) << ", " << serialize(Var
.Get().y
);
582 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarT
<Vector3fT
>& Var
)
584 m_Out
<< serialize(Var
.Get().x
) << ", " << serialize(Var
.Get().y
) << ", " << serialize(Var
.Get().z
);
588 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarT
<Vector3dT
>& Var
)
590 m_Out
<< serialize(Var
.Get().x
) << ", " << serialize(Var
.Get().y
) << ", " << serialize(Var
.Get().z
);
594 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarT
<BoundingBox3dT
>& Var
)
596 m_Out
<< serialize(Var
.Get().Min
.x
) << ", " << serialize(Var
.Get().Min
.y
) << ", " << serialize(Var
.Get().Min
.z
) << ", ";
597 m_Out
<< serialize(Var
.Get().Max
.x
) << ", " << serialize(Var
.Get().Max
.y
) << ", " << serialize(Var
.Get().Max
.z
);
601 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarArrayT
<uint32_t>& Var
)
605 for (unsigned int i
= 0; i
< Var
.Size(); i
++)
608 if (i
+1 < Var
.Size()) m_Out
<< ", ";
615 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarArrayT
<uint16_t>& Var
)
619 for (unsigned int i
= 0; i
< Var
.Size(); i
++)
622 if (i
+1 < Var
.Size()) m_Out
<< ", ";
629 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarArrayT
<uint8_t>& Var
)
633 for (unsigned int i
= 0; i
< Var
.Size(); i
++)
635 m_Out
<< uint16_t(Var
[i
]); // Write numbers, not characters.
636 if (i
+1 < Var
.Size()) m_Out
<< ", ";
643 void VarVisitorToLuaCodeT::visit(const cf::TypeSys::VarArrayT
<std::string
>& Var
)
647 for (unsigned int i
= 0; i
< Var
.Size(); i
++)
650 if (i
+1 < Var
.Size()) m_Out
<< ", ";
657 void VarVisitorToLuaCodeT::WriteString(const std::string
& s
) const
659 for (size_t i
= 0; i
< s
.size(); i
++)
660 if (iscntrl(s
[i
]) || s
[i
] == '"' || s
[i
] == '\\')
662 std::string Equals
= "";
664 while (s
.find("[" + Equals
+ "[") != std::string::npos
||
665 s
.find("]" + Equals
+ "]") != std::string::npos
)
668 // Why do we write an extra newline following the opening long bracket?
669 // The answer is given in the Lua reference manual:
671 // > For convenience, when the opening long bracket is immediately
672 // > followed by a newline, the newline is not included in the string.
674 // That is, if s begins with a character that is *not* a newline, prepending the extra newline
675 // doesn't make a difference. But if the first character in s happened to be a newline, it would
676 // get lost if the extra newline was not written.
677 m_Out
<< "[" << Equals
<< "[\n";
679 m_Out
<< "]" << Equals
<< "]";
683 m_Out
<< "\"" << s
<< "\"";