collections_glue.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /**************************************************************************/
  2. /* collections_glue.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #include "collections_glue.h"
  31. #ifdef MONO_GLUE_ENABLED
  32. #include <mono/metadata/exception.h>
  33. #include "../mono_gd/gd_mono_cache.h"
  34. #include "../mono_gd/gd_mono_class.h"
  35. #include "../mono_gd/gd_mono_utils.h"
  36. Array *godot_icall_Array_Ctor() {
  37. return memnew(Array);
  38. }
  39. void godot_icall_Array_Dtor(Array *ptr) {
  40. memdelete(ptr);
  41. }
  42. MonoObject *godot_icall_Array_At(Array *ptr, int32_t index) {
  43. if (index < 0 || index >= ptr->size()) {
  44. GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
  45. return NULL;
  46. }
  47. return GDMonoMarshal::variant_to_mono_object(ptr->operator[](index));
  48. }
  49. MonoObject *godot_icall_Array_At_Generic(Array *ptr, int32_t index, uint32_t type_encoding, GDMonoClass *type_class) {
  50. if (index < 0 || index >= ptr->size()) {
  51. GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
  52. return NULL;
  53. }
  54. return GDMonoMarshal::variant_to_mono_object(ptr->operator[](index), ManagedType(type_encoding, type_class));
  55. }
  56. void godot_icall_Array_SetAt(Array *ptr, int32_t index, MonoObject *value) {
  57. if (index < 0 || index >= ptr->size()) {
  58. GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
  59. return;
  60. }
  61. ptr->operator[](index) = GDMonoMarshal::mono_object_to_variant(value);
  62. }
  63. int32_t godot_icall_Array_Count(Array *ptr) {
  64. return ptr->size();
  65. }
  66. int32_t godot_icall_Array_Add(Array *ptr, MonoObject *item) {
  67. ptr->append(GDMonoMarshal::mono_object_to_variant(item));
  68. return ptr->size();
  69. }
  70. void godot_icall_Array_Clear(Array *ptr) {
  71. ptr->clear();
  72. }
  73. MonoBoolean godot_icall_Array_Contains(Array *ptr, MonoObject *item) {
  74. return ptr->find(GDMonoMarshal::mono_object_to_variant(item)) != -1;
  75. }
  76. void godot_icall_Array_CopyTo(Array *ptr, MonoArray *array, int32_t array_index) {
  77. unsigned int count = ptr->size();
  78. if (mono_array_length(array) < (array_index + count)) {
  79. MonoException *exc = mono_get_exception_argument("", "Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
  80. GDMonoUtils::set_pending_exception(exc);
  81. return;
  82. }
  83. for (unsigned int i = 0; i < count; i++) {
  84. MonoObject *boxed = GDMonoMarshal::variant_to_mono_object(ptr->operator[](i));
  85. mono_array_setref(array, array_index, boxed);
  86. array_index++;
  87. }
  88. }
  89. Array *godot_icall_Array_Ctor_MonoArray(MonoArray *mono_array) {
  90. Array *godot_array = memnew(Array);
  91. unsigned int count = mono_array_length(mono_array);
  92. godot_array->resize(count);
  93. for (unsigned int i = 0; i < count; i++) {
  94. MonoObject *item = mono_array_get(mono_array, MonoObject *, i);
  95. godot_icall_Array_SetAt(godot_array, i, item);
  96. }
  97. return godot_array;
  98. }
  99. Array *godot_icall_Array_Duplicate(Array *ptr, MonoBoolean deep) {
  100. return memnew(Array(ptr->duplicate(deep)));
  101. }
  102. Array *godot_icall_Array_Concatenate(Array *left, Array *right) {
  103. int count = left->size() + right->size();
  104. Array *new_array = memnew(Array(left->duplicate(false)));
  105. new_array->resize(count);
  106. for (unsigned int i = 0; i < (unsigned int)right->size(); i++) {
  107. new_array->operator[](i + left->size()) = right->operator[](i);
  108. }
  109. return new_array;
  110. }
  111. int32_t godot_icall_Array_IndexOf(Array *ptr, MonoObject *item) {
  112. return ptr->find(GDMonoMarshal::mono_object_to_variant(item));
  113. }
  114. void godot_icall_Array_Insert(Array *ptr, int32_t index, MonoObject *item) {
  115. if (index < 0 || index > ptr->size()) {
  116. GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
  117. return;
  118. }
  119. ptr->insert(index, GDMonoMarshal::mono_object_to_variant(item));
  120. }
  121. MonoBoolean godot_icall_Array_Remove(Array *ptr, MonoObject *item) {
  122. int idx = ptr->find(GDMonoMarshal::mono_object_to_variant(item));
  123. if (idx >= 0) {
  124. ptr->remove(idx);
  125. return true;
  126. }
  127. return false;
  128. }
  129. void godot_icall_Array_RemoveAt(Array *ptr, int32_t index) {
  130. if (index < 0 || index >= ptr->size()) {
  131. GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
  132. return;
  133. }
  134. ptr->remove(index);
  135. }
  136. int32_t godot_icall_Array_Resize(Array *ptr, int32_t new_size) {
  137. return (int32_t)ptr->resize(new_size);
  138. }
  139. void godot_icall_Array_Shuffle(Array *ptr) {
  140. ptr->shuffle();
  141. }
  142. void godot_icall_Array_Generic_GetElementTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class) {
  143. MonoType *elem_type = mono_reflection_type_get_type(refltype);
  144. *type_encoding = mono_type_get_type(elem_type);
  145. MonoClass *type_class_raw = mono_class_from_mono_type(elem_type);
  146. *type_class = GDMono::get_singleton()->get_class(type_class_raw);
  147. }
  148. MonoString *godot_icall_Array_ToString(Array *ptr) {
  149. return GDMonoMarshal::mono_string_from_godot(Variant(*ptr).operator String());
  150. }
  151. Dictionary *godot_icall_Dictionary_Ctor() {
  152. return memnew(Dictionary);
  153. }
  154. void godot_icall_Dictionary_Dtor(Dictionary *ptr) {
  155. memdelete(ptr);
  156. }
  157. MonoObject *godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key) {
  158. Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
  159. if (ret == NULL) {
  160. MonoObject *exc = mono_object_new(mono_domain_get(), CACHED_CLASS(KeyNotFoundException)->get_mono_ptr());
  161. #ifdef DEBUG_ENABLED
  162. CRASH_COND(!exc);
  163. #endif
  164. GDMonoUtils::runtime_object_init(exc, CACHED_CLASS(KeyNotFoundException));
  165. GDMonoUtils::set_pending_exception((MonoException *)exc);
  166. return NULL;
  167. }
  168. return GDMonoMarshal::variant_to_mono_object(ret);
  169. }
  170. MonoObject *godot_icall_Dictionary_GetValue_Generic(Dictionary *ptr, MonoObject *key, uint32_t type_encoding, GDMonoClass *type_class) {
  171. Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
  172. if (ret == NULL) {
  173. MonoObject *exc = mono_object_new(mono_domain_get(), CACHED_CLASS(KeyNotFoundException)->get_mono_ptr());
  174. #ifdef DEBUG_ENABLED
  175. CRASH_COND(!exc);
  176. #endif
  177. GDMonoUtils::runtime_object_init(exc, CACHED_CLASS(KeyNotFoundException));
  178. GDMonoUtils::set_pending_exception((MonoException *)exc);
  179. return NULL;
  180. }
  181. return GDMonoMarshal::variant_to_mono_object(ret, ManagedType(type_encoding, type_class));
  182. }
  183. void godot_icall_Dictionary_SetValue(Dictionary *ptr, MonoObject *key, MonoObject *value) {
  184. ptr->operator[](GDMonoMarshal::mono_object_to_variant(key)) = GDMonoMarshal::mono_object_to_variant(value);
  185. }
  186. Array *godot_icall_Dictionary_Keys(Dictionary *ptr) {
  187. return memnew(Array(ptr->keys()));
  188. }
  189. Array *godot_icall_Dictionary_Values(Dictionary *ptr) {
  190. return memnew(Array(ptr->values()));
  191. }
  192. int32_t godot_icall_Dictionary_Count(Dictionary *ptr) {
  193. return ptr->size();
  194. }
  195. int32_t godot_icall_Dictionary_KeyValuePairs(Dictionary *ptr, Array **keys, Array **values) {
  196. *keys = godot_icall_Dictionary_Keys(ptr);
  197. *values = godot_icall_Dictionary_Values(ptr);
  198. return godot_icall_Dictionary_Count(ptr);
  199. }
  200. void godot_icall_Dictionary_KeyValuePairAt(Dictionary *ptr, int index, MonoObject **key, MonoObject **value) {
  201. *key = GDMonoMarshal::variant_to_mono_object(ptr->get_key_at_index(index));
  202. *value = GDMonoMarshal::variant_to_mono_object(ptr->get_value_at_index(index));
  203. }
  204. void godot_icall_Dictionary_KeyValuePairAt_Generic(Dictionary *ptr, int index, MonoObject **key, MonoObject **value, uint32_t value_type_encoding, GDMonoClass *value_type_class) {
  205. ManagedType type(value_type_encoding, value_type_class);
  206. *key = GDMonoMarshal::variant_to_mono_object(ptr->get_key_at_index(index));
  207. *value = GDMonoMarshal::variant_to_mono_object(ptr->get_value_at_index(index), type);
  208. }
  209. void godot_icall_Dictionary_Add(Dictionary *ptr, MonoObject *key, MonoObject *value) {
  210. Variant varKey = GDMonoMarshal::mono_object_to_variant(key);
  211. Variant *ret = ptr->getptr(varKey);
  212. if (ret != NULL) {
  213. GDMonoUtils::set_pending_exception(mono_get_exception_argument("key", "An element with the same key already exists"));
  214. return;
  215. }
  216. ptr->operator[](varKey) = GDMonoMarshal::mono_object_to_variant(value);
  217. }
  218. void godot_icall_Dictionary_Clear(Dictionary *ptr) {
  219. ptr->clear();
  220. }
  221. MonoBoolean godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, MonoObject *value) {
  222. // no dupes
  223. Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
  224. return ret != NULL && *ret == GDMonoMarshal::mono_object_to_variant(value);
  225. }
  226. MonoBoolean godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key) {
  227. return ptr->has(GDMonoMarshal::mono_object_to_variant(key));
  228. }
  229. Dictionary *godot_icall_Dictionary_Duplicate(Dictionary *ptr, MonoBoolean deep) {
  230. return memnew(Dictionary(ptr->duplicate(deep)));
  231. }
  232. MonoBoolean godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key) {
  233. return ptr->erase(GDMonoMarshal::mono_object_to_variant(key));
  234. }
  235. MonoBoolean godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value) {
  236. Variant varKey = GDMonoMarshal::mono_object_to_variant(key);
  237. // no dupes
  238. Variant *ret = ptr->getptr(varKey);
  239. if (ret != NULL && *ret == GDMonoMarshal::mono_object_to_variant(value)) {
  240. ptr->erase(varKey);
  241. return true;
  242. }
  243. return false;
  244. }
  245. MonoBoolean godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value) {
  246. Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
  247. if (ret == NULL) {
  248. *value = NULL;
  249. return false;
  250. }
  251. *value = GDMonoMarshal::variant_to_mono_object(ret);
  252. return true;
  253. }
  254. MonoBoolean godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObject *key, MonoObject **value, uint32_t type_encoding, GDMonoClass *type_class) {
  255. Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
  256. if (ret == NULL) {
  257. *value = NULL;
  258. return false;
  259. }
  260. *value = GDMonoMarshal::variant_to_mono_object(ret, ManagedType(type_encoding, type_class));
  261. return true;
  262. }
  263. void godot_icall_Dictionary_Generic_GetValueTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class) {
  264. MonoType *value_type = mono_reflection_type_get_type(refltype);
  265. *type_encoding = mono_type_get_type(value_type);
  266. MonoClass *type_class_raw = mono_class_from_mono_type(value_type);
  267. *type_class = GDMono::get_singleton()->get_class(type_class_raw);
  268. }
  269. MonoString *godot_icall_Dictionary_ToString(Dictionary *ptr) {
  270. return GDMonoMarshal::mono_string_from_godot(Variant(*ptr).operator String());
  271. }
  272. void godot_register_collections_icalls() {
  273. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Ctor", godot_icall_Array_Ctor);
  274. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Ctor_MonoArray", godot_icall_Array_Ctor_MonoArray);
  275. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Dtor", godot_icall_Array_Dtor);
  276. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_At", godot_icall_Array_At);
  277. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_At_Generic", godot_icall_Array_At_Generic);
  278. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_SetAt", godot_icall_Array_SetAt);
  279. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Count", godot_icall_Array_Count);
  280. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Add", godot_icall_Array_Add);
  281. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Clear", godot_icall_Array_Clear);
  282. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Concatenate", godot_icall_Array_Concatenate);
  283. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Contains", godot_icall_Array_Contains);
  284. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_CopyTo", godot_icall_Array_CopyTo);
  285. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Duplicate", godot_icall_Array_Duplicate);
  286. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_IndexOf", godot_icall_Array_IndexOf);
  287. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Insert", godot_icall_Array_Insert);
  288. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Remove", godot_icall_Array_Remove);
  289. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_RemoveAt", godot_icall_Array_RemoveAt);
  290. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Resize", godot_icall_Array_Resize);
  291. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Shuffle", godot_icall_Array_Shuffle);
  292. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Generic_GetElementTypeInfo", godot_icall_Array_Generic_GetElementTypeInfo);
  293. GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_ToString", godot_icall_Array_ToString);
  294. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Ctor", godot_icall_Dictionary_Ctor);
  295. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Dtor", godot_icall_Dictionary_Dtor);
  296. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_GetValue", godot_icall_Dictionary_GetValue);
  297. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_GetValue_Generic", godot_icall_Dictionary_GetValue_Generic);
  298. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_SetValue", godot_icall_Dictionary_SetValue);
  299. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Keys", godot_icall_Dictionary_Keys);
  300. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Values", godot_icall_Dictionary_Values);
  301. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Count", godot_icall_Dictionary_Count);
  302. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairs", godot_icall_Dictionary_KeyValuePairs);
  303. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairAt", godot_icall_Dictionary_KeyValuePairAt);
  304. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairAt_Generic", godot_icall_Dictionary_KeyValuePairAt_Generic);
  305. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Add", godot_icall_Dictionary_Add);
  306. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Clear", godot_icall_Dictionary_Clear);
  307. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Contains", godot_icall_Dictionary_Contains);
  308. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_ContainsKey", godot_icall_Dictionary_ContainsKey);
  309. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Duplicate", godot_icall_Dictionary_Duplicate);
  310. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_RemoveKey", godot_icall_Dictionary_RemoveKey);
  311. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Remove", godot_icall_Dictionary_Remove);
  312. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_TryGetValue", godot_icall_Dictionary_TryGetValue);
  313. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_TryGetValue_Generic", godot_icall_Dictionary_TryGetValue_Generic);
  314. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Generic_GetValueTypeInfo", godot_icall_Dictionary_Generic_GetValueTypeInfo);
  315. GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_ToString", godot_icall_Dictionary_ToString);
  316. }
  317. #endif // MONO_GLUE_ENABLED