Variant.pkg 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. $#include "Core/Variant.h"
  2. $#include "IO/VectorBuffer.h"
  3. enum VariantType
  4. {
  5. VAR_NONE = 0,
  6. VAR_INT,
  7. VAR_BOOL,
  8. VAR_FLOAT,
  9. VAR_VECTOR2,
  10. VAR_VECTOR3,
  11. VAR_VECTOR4,
  12. VAR_QUATERNION,
  13. VAR_COLOR,
  14. VAR_STRING,
  15. VAR_BUFFER,
  16. VAR_VOIDPTR,
  17. VAR_RESOURCEREF,
  18. VAR_RESOURCEREFLIST,
  19. VAR_VARIANTVECTOR,
  20. VAR_VARIANTMAP,
  21. VAR_INTRECT,
  22. VAR_INTVECTOR2,
  23. VAR_PTR,
  24. VAR_MATRIX3,
  25. VAR_MATRIX3X4,
  26. VAR_MATRIX4,
  27. VAR_DOUBLE,
  28. VAR_STRINGVECTOR,
  29. VAR_RECT,
  30. VAR_INTVECTOR3,
  31. VAR_INT64,
  32. MAX_VAR_TYPES
  33. };
  34. struct ResourceRef
  35. {
  36. ResourceRef();
  37. ResourceRef(StringHash type);
  38. ResourceRef(StringHash type, String name);
  39. ResourceRef(String type, String name);
  40. ResourceRef(const ResourceRef& rhs);
  41. ~ResourceRef();
  42. StringHash type_ @ type;
  43. String name_ @ name;
  44. bool operator ==(const ResourceRef& rhs) const;
  45. };
  46. struct ResourceRefList
  47. {
  48. ResourceRefList();
  49. ResourceRefList(StringHash type);
  50. ~ResourceRefList();
  51. StringHash type_ @ type;
  52. bool operator ==(const ResourceRefList& rhs) const;
  53. };
  54. class Variant
  55. {
  56. static void _Setup(const char* type);
  57. // NOTE: do not change the constructor overloads order without also changing the manually coded implementation below
  58. Variant();
  59. Variant(const Variant& value); // This overload works for all Lua types that are convertible into a Variant
  60. Variant(const char* type, const char* value); // For storing a numerical type into Variant , value could be just a number
  61. Variant(VariantType type, const char* value);
  62. ~Variant();
  63. void Clear();
  64. bool operator ==(const Variant& rhs) const; // rhs can be any Lua types convertible into a Variant
  65. void Set(const Variant& rhs); // rhs can be any Lua types convertible into a Variant
  66. void* Get(const char* type = 0) const; // "Generic" get which is only possible in Lua scripting
  67. // All below getters are preserved for backward compatibility and for compatibility with C++ and AngelScript API
  68. int GetInt() const;
  69. unsigned GetUInt() const;
  70. long long int GetInt64() const;
  71. unsigned long long int GetUInt64() const;
  72. StringHash GetStringHash() const;
  73. bool GetBool() const;
  74. float GetFloat() const;
  75. double GetDouble() const;
  76. const Vector2& GetVector2() const;
  77. const Vector3& GetVector3() const;
  78. const Vector4& GetVector4() const;
  79. const Quaternion& GetQuaternion() const;
  80. const Color& GetColor() const;
  81. const String GetString() const;
  82. const PODVector<unsigned char>& GetBuffer @ GetRawBuffer() const;
  83. VectorBuffer GetVectorBuffer @ GetBuffer() const; // For backward compatibility reason, keep the old alias
  84. void* GetVoidPtr(const char* type) const;
  85. const ResourceRef& GetResourceRef() const;
  86. const ResourceRefList& GetResourceRefList() const;
  87. const Vector<Variant>& GetVariantVector() const;
  88. const VariantMap& GetVariantMap() const;
  89. const Vector<String>& GetStringVector() const;
  90. const Rect& GetRect() const;
  91. const IntRect& GetIntRect() const;
  92. const IntVector2& GetIntVector2() const;
  93. const IntVector3& GetIntVector3() const;
  94. RefCounted* GetPtr(const char* type) const;
  95. const Matrix3& GetMatrix3() const;
  96. const Matrix3x4& GetMatrix3x4() const;
  97. const Matrix4& GetMatrix4() const;
  98. VariantType GetType() const;
  99. String GetTypeName() const;
  100. String ToString() const;
  101. bool IsZero() const;
  102. bool IsEmpty() const;
  103. tolua_readonly tolua_property__get_set VariantType type;
  104. tolua_readonly tolua_property__get_set String typeName;
  105. tolua_readonly tolua_property__is_set bool zero;
  106. tolua_readonly tolua_property__is_set bool empty;
  107. };
  108. $[
  109. -- Call the setup method and then hide it immediately
  110. Variant:_Setup("Variant")
  111. Variant:_Setup("const Variant")
  112. Variant._Setup = nil
  113. $]
  114. ${
  115. static int VariantToStringEventHandler(lua_State* tolua_S)
  116. {
  117. lua_pushstring(tolua_S, static_cast<Variant*>(tolua_tousertype(tolua_S, -1, 0))->ToString().CString());
  118. return 1;
  119. }
  120. static int VariantConcatEventHandler(lua_State* tolua_S)
  121. {
  122. // __concat event handler has two operands, check whether the first operand is variant or the second is (one of them must be)
  123. // This event handler has two code branches to handle both cases differently based on the isFirst flag
  124. // In case of both operands are variant then the handler handles the case as if it is isFirst case then below lua_concat() call
  125. // would in turn trigger the handler the second time to handle the second operand using the !isFirst code branch
  126. bool isFirst = lua_isuserdata(tolua_S, 1);
  127. if (isFirst)
  128. lua_pushvalue(tolua_S, 1); // isFirst stack: variant1 operand2 variant1
  129. VariantToStringEventHandler(tolua_S); // isFirst stack: variant1 operand2 variant1 string1 | !isFirst: operand1 variant2 string2
  130. if (isFirst)
  131. {
  132. lua_replace(tolua_S, 1); // isFirst stack: string1 operand2 variant1
  133. lua_pop(tolua_S, 1); // isFirst stack: string1 operand2
  134. }
  135. else
  136. lua_remove(tolua_S, -2); // !isFirst stack: operand1 string2
  137. lua_concat(tolua_S, 2);
  138. return 1;
  139. }
  140. #define TOLUA_DISABLE_tolua_CoreLuaAPI_Variant__Setup00
  141. static int tolua_CoreLuaAPI_Variant__Setup00(lua_State* tolua_S)
  142. {
  143. // Register our own version of metamethod to handle __tostring and __concat events
  144. luaL_getmetatable(tolua_S, tolua_tostring(tolua_S, 2, 0));
  145. lua_pushstring(tolua_S, "__tostring");
  146. lua_pushcfunction(tolua_S, VariantToStringEventHandler);
  147. lua_rawset(tolua_S, -3);
  148. lua_pushstring(tolua_S, "__concat");
  149. lua_pushcfunction(tolua_S, VariantConcatEventHandler);
  150. lua_rawset(tolua_S, -3);
  151. lua_pop(tolua_S, 1);
  152. return 0;
  153. }
  154. // NOTE: the index number must match with the above variant constructor overloads order)
  155. // Forward declaration
  156. static int tolua_CoreLuaAPI_Variant_new00(lua_State* tolua_S);
  157. static int tolua_CoreLuaAPI_Variant_new00_local(lua_State* tolua_S);
  158. static bool VariantNewImpl(lua_State* tolua_S, bool gc)
  159. {
  160. tolua_Error tolua_err;
  161. if (tolua_isusertable(tolua_S, 1, "Variant", 0, &tolua_err) && lua_gettop(tolua_S) == 2)
  162. {
  163. Variant* tolua_ret = Mtolua_new(Variant());
  164. ToluaToVariant(tolua_S, 2, 0, *tolua_ret);
  165. tolua_pushusertype(tolua_S, static_cast<void*>(tolua_ret), "Variant");
  166. if (gc)
  167. tolua_register_gc(tolua_S, lua_gettop(tolua_S));
  168. return true;
  169. }
  170. return false;
  171. }
  172. #define TOLUA_DISABLE_tolua_CoreLuaAPI_Variant_new01
  173. static int tolua_CoreLuaAPI_Variant_new01(lua_State* tolua_S)
  174. {
  175. return VariantNewImpl(tolua_S, false) ? 1 : tolua_CoreLuaAPI_Variant_new00(tolua_S);
  176. }
  177. #define TOLUA_DISABLE_tolua_CoreLuaAPI_Variant_new01_local
  178. static int tolua_CoreLuaAPI_Variant_new01_local(lua_State* tolua_S)
  179. {
  180. return VariantNewImpl(tolua_S, true) ? 1 : tolua_CoreLuaAPI_Variant_new00_local(tolua_S);
  181. }
  182. #define TOLUA_DISABLE_tolua_CoreLuaAPI_Variant__eq00
  183. static int tolua_CoreLuaAPI_Variant__eq00(lua_State* tolua_S)
  184. {
  185. #ifndef TOLUA_RELEASE
  186. tolua_Error tolua_err;
  187. if (tolua_isusertype(tolua_S, 1, "const Variant", 0, &tolua_err) && lua_gettop(tolua_S) == 2)
  188. #endif
  189. {
  190. const Variant* self = static_cast<const Variant*>(tolua_tousertype(tolua_S, 1, 0));
  191. Variant rhs;
  192. ToluaToVariant(tolua_S, 2, 0, rhs);
  193. #ifndef TOLUA_RELEASE
  194. if (!self)
  195. tolua_error(tolua_S, "invalid 'self' in function 'operator=='", NULL);
  196. else
  197. #endif
  198. {
  199. tolua_pushboolean(tolua_S, self->operator ==(rhs));
  200. return 1;
  201. }
  202. }
  203. #ifndef TOLUA_RELEASE
  204. tolua_error(tolua_S, "#ferror in function '.eq'.", &tolua_err);
  205. return 0;
  206. #endif
  207. }
  208. #define TOLUA_DISABLE_tolua_CoreLuaAPI_Variant_Set00
  209. static int tolua_CoreLuaAPI_Variant_Set00(lua_State* tolua_S)
  210. {
  211. #ifndef TOLUA_RELEASE
  212. tolua_Error tolua_err;
  213. if (tolua_isusertype(tolua_S, 1, "Variant", 0, &tolua_err) && lua_gettop(tolua_S) == 2)
  214. #endif
  215. {
  216. Variant * self = static_cast<Variant*>(tolua_tousertype(tolua_S, 1, 0));
  217. Variant rhs;
  218. ToluaToVariant(tolua_S, 2, 0, rhs);
  219. const char* type = tolua_tostring(tolua_S, 3, 0);
  220. #ifndef TOLUA_RELEASE
  221. if (!self)
  222. tolua_error(tolua_S, "invalid 'self' in function 'Set'", NULL);
  223. else
  224. #endif
  225. {
  226. *self = rhs;
  227. return 0;
  228. }
  229. }
  230. #ifndef TOLUA_RELEASE
  231. tolua_error(tolua_S, "#ferror in function 'Set'.", &tolua_err);
  232. return 0;
  233. #endif
  234. }
  235. #define TOLUA_DISABLE_tolua_CoreLuaAPI_Variant_Get00
  236. static int tolua_CoreLuaAPI_Variant_Get00(lua_State* tolua_S)
  237. {
  238. #ifndef TOLUA_RELEASE
  239. tolua_Error tolua_err;
  240. if (tolua_isusertype(tolua_S, 1, "const Variant", 0, &tolua_err) && tolua_isstring(tolua_S, 2, 1, &tolua_err) &&
  241. tolua_isnoobj(tolua_S, 3, &tolua_err))
  242. #endif
  243. {
  244. const Variant* self = static_cast<const Variant*>(tolua_tousertype(tolua_S, 1, 0));
  245. const char* type = tolua_tostring(tolua_S, 2, 0);
  246. #ifndef TOLUA_RELEASE
  247. if (!self)
  248. tolua_error(tolua_S, "invalid 'self' in function 'Get'", NULL);
  249. else
  250. #endif
  251. {
  252. ToluaPushVariant(tolua_S, self, type);
  253. return 1;
  254. }
  255. }
  256. #ifndef TOLUA_RELEASE
  257. tolua_error(tolua_S, "#ferror in function 'Get'.", &tolua_err);
  258. return 0;
  259. #endif
  260. }
  261. #define TOLUA_DISABLE_tolua_CoreLuaAPI_Variant_GetVoidPtr00
  262. static int tolua_CoreLuaAPI_Variant_GetVoidPtr00(lua_State* tolua_S)
  263. {
  264. #ifndef TOLUA_RELEASE
  265. tolua_Error tolua_err;
  266. if (
  267. !tolua_isusertype(tolua_S,1,"const Variant",0,&tolua_err) ||
  268. !tolua_isstring(tolua_S,2,0,&tolua_err) ||
  269. !tolua_isnoobj(tolua_S,3,&tolua_err)
  270. )
  271. goto tolua_lerror;
  272. else
  273. #endif
  274. {
  275. const Variant* self = (const Variant*) tolua_tousertype(tolua_S,1,0);
  276. const char* type = ((const char*) tolua_tostring(tolua_S,2,0));
  277. #ifndef TOLUA_RELEASE
  278. if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetVoidPtr'", NULL);
  279. #endif
  280. {
  281. // Use the safer version which first check the type provided through Lua script to prevent VM crashes on invalid type
  282. ToluaPushRegisteredUserType(tolua_S, static_cast<void*>(self->GetVoidPtr()), type);
  283. }
  284. }
  285. return 1;
  286. #ifndef TOLUA_RELEASE
  287. tolua_lerror:
  288. tolua_error(tolua_S,"#ferror in function 'GetVoidPtr'.",&tolua_err);
  289. return 0;
  290. #endif
  291. }
  292. #define TOLUA_DISABLE_tolua_CoreLuaAPI_Variant_GetPtr00
  293. static int tolua_CoreLuaAPI_Variant_GetPtr00(lua_State* tolua_S)
  294. {
  295. #ifndef TOLUA_RELEASE
  296. tolua_Error tolua_err;
  297. if (
  298. !tolua_isusertype(tolua_S,1,"const Variant",0,&tolua_err) ||
  299. !tolua_isstring(tolua_S,2,1,&tolua_err) ||
  300. !tolua_isnoobj(tolua_S,3,&tolua_err)
  301. )
  302. goto tolua_lerror;
  303. else
  304. #endif
  305. {
  306. const Variant* self = (const Variant*) tolua_tousertype(tolua_S,1,0);
  307. const char* type = ((const char*) tolua_tostring(tolua_S,2,0));
  308. #ifndef TOLUA_RELEASE
  309. if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetPtr'", NULL);
  310. #endif
  311. {
  312. ToluaPushRegisteredUserType(tolua_S, static_cast<void*>(self->GetPtr()), type);
  313. }
  314. }
  315. return 1;
  316. #ifndef TOLUA_RELEASE
  317. tolua_lerror:
  318. tolua_error(tolua_S,"#ferror in function 'GetPtr'.",&tolua_err);
  319. return 0;
  320. #endif
  321. }
  322. $}
  323. class VariantMap
  324. {
  325. static void _Setup(const char* type);
  326. VariantMap();
  327. ~VariantMap();
  328. };
  329. $[
  330. VariantMap:_Setup("VariantMap")
  331. VariantMap:_Setup("const VariantMap")
  332. VariantMap._Setup = nil
  333. $]
  334. ${
  335. static int VariantMapIndexEventHandler(lua_State* tolua_S)
  336. {
  337. int t = lua_type(tolua_S, 2);
  338. StringHash key;
  339. if (t == LUA_TSTRING)
  340. key = StringHash(lua_tostring(tolua_S, 2));
  341. else if (t == LUA_TNUMBER)
  342. key = StringHash((unsigned)lua_tonumber(tolua_S, 2));
  343. else if (t == LUA_TUSERDATA)
  344. {
  345. tolua_Error error;
  346. if (tolua_isusertype(tolua_S, 2, "StringHash", 0, &error))
  347. key = *static_cast<StringHash*>(tolua_tousertype(tolua_S, 2, 0));
  348. }
  349. Variant* variant = key ? static_cast<const VariantMap*>(tolua_tousertype(tolua_S, 1, 0))->operator [](key) : 0;
  350. if (variant)
  351. tolua_pushusertype(tolua_S, variant, "Variant");
  352. else
  353. lua_pushnil(tolua_S);
  354. return 1;
  355. }
  356. static int VariantMapNewIndexEventHandler(lua_State* tolua_S)
  357. {
  358. int t = lua_type(tolua_S, 2);
  359. StringHash key;
  360. if (t == LUA_TSTRING)
  361. key = StringHash(lua_tostring(tolua_S, 2));
  362. else if (t == LUA_TNUMBER)
  363. key = StringHash((unsigned)lua_tonumber(tolua_S, 2));
  364. else if (t == LUA_TUSERDATA)
  365. {
  366. tolua_Error error;
  367. if (tolua_isusertype(tolua_S, 2, "StringHash", 0, &error))
  368. key = *static_cast<StringHash*>(tolua_tousertype(tolua_S, 2, 0));
  369. else
  370. return 0;
  371. }
  372. else
  373. return 0;
  374. Variant& variant = static_cast<VariantMap*>(tolua_tousertype(tolua_S, 1, 0))->operator [](key); // autovivification
  375. ToluaToVariant(tolua_S, 3, 0, variant);
  376. return 0;
  377. }
  378. #define TOLUA_DISABLE_tolua_CoreLuaAPI_VariantMap__Setup00
  379. static int tolua_CoreLuaAPI_VariantMap__Setup00(lua_State* tolua_S)
  380. {
  381. // Register our own version of metamethod to handle __index and __newindex events
  382. luaL_getmetatable(tolua_S, tolua_tostring(tolua_S, 2, 0));
  383. lua_pushstring(tolua_S, "__index");
  384. lua_pushcfunction(tolua_S, VariantMapIndexEventHandler);
  385. lua_rawset(tolua_S, -3);
  386. lua_pushstring(tolua_S, "__newindex");
  387. lua_pushcfunction(tolua_S, VariantMapNewIndexEventHandler);
  388. lua_rawset(tolua_S, -3);
  389. lua_pop(tolua_S, 1);
  390. return 0;
  391. }
  392. $}