stl.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #include "pybind11.h"
  2. #include <array>
  3. #include <vector>
  4. #include <list>
  5. #include <deque>
  6. #include <forward_list>
  7. #include <map>
  8. #include <unordered_map>
  9. namespace pkbind {
  10. template <typename T, std::size_t N>
  11. struct type_caster<std::array<T, N>> {
  12. std::array<T, N> data;
  13. template <typename U>
  14. static handle cast(U&& src, return_value_policy policy, handle parent) {
  15. auto list = pkbind::list();
  16. for(auto&& item: src) {
  17. list.append(pkbind::cast(std::move(item), policy, parent));
  18. }
  19. return list;
  20. }
  21. bool load(handle src, bool convert) {
  22. if(!isinstance<list>(src)) { return false; }
  23. auto list = src.cast<pkbind::list>();
  24. if(list.size() != N) { return false; }
  25. for(int i = 0; i < N; ++i) {
  26. type_caster<T> caster;
  27. if(!caster.load(list[i], convert)) { return false; }
  28. data[i] = std::move(caster.value());
  29. }
  30. return true;
  31. }
  32. std::array<T, N>& value() { return data; }
  33. constexpr inline static bool is_temporary_v = true;
  34. };
  35. template <typename T>
  36. constexpr bool is_py_list_like_v = false;
  37. template <typename T, typename Allocator>
  38. constexpr bool is_py_list_like_v<std::vector<T, Allocator>> = true;
  39. template <typename T, typename Allocator>
  40. constexpr bool is_py_list_like_v<std::list<T, Allocator>> = true;
  41. template <typename T, typename Allocator>
  42. constexpr bool is_py_list_like_v<std::deque<T, Allocator>> = true;
  43. template <>
  44. struct type_caster<std::vector<bool>> {
  45. std::vector<bool> data;
  46. template <typename U>
  47. static object cast(U&& src, return_value_policy policy, handle parent) {
  48. auto list = pkbind::list();
  49. for(auto&& item: src) {
  50. list.append(pkbind::cast(bool(item), policy, parent));
  51. }
  52. return list;
  53. }
  54. bool load(handle src, bool convert) {
  55. if(!isinstance<list>(src)) { return false; }
  56. auto list = src.cast<pkbind::list>();
  57. data.clear();
  58. data.reserve(list.size());
  59. for(auto item: list) {
  60. type_caster<bool> caster;
  61. if(!caster.load(item, convert)) { return false; }
  62. data.push_back(caster.value());
  63. }
  64. return true;
  65. }
  66. std::vector<bool>& value() { return data; }
  67. constexpr inline static bool is_temporary_v = true;
  68. };
  69. template <typename T>
  70. struct type_caster<T, std::enable_if_t<is_py_list_like_v<T>>> {
  71. T data;
  72. template <typename U>
  73. static object cast(U&& src, return_value_policy policy, handle parent) {
  74. auto list = pkbind::list();
  75. for(auto&& item: src) {
  76. list.append(pkbind::cast(std::move(item), policy, parent));
  77. }
  78. return list;
  79. }
  80. bool load(handle src, bool convert) {
  81. if(!isinstance<list>(src)) { return false; }
  82. auto list = src.cast<pkbind::list>();
  83. for(auto item: list) {
  84. type_caster<typename T::value_type> caster;
  85. if(!caster.load(item, convert)) { return false; }
  86. data.push_back(std::move(caster.value()));
  87. }
  88. return true;
  89. }
  90. T& value() { return data; }
  91. constexpr inline static bool is_temporary_v = true;
  92. };
  93. template <typename T>
  94. constexpr bool is_py_map_like_v = false;
  95. template <typename Key, typename T, typename Compare, typename Allocator>
  96. constexpr bool is_py_map_like_v<std::map<Key, T, Compare, Allocator>> = true;
  97. template <typename Key, typename T, typename Hash, typename KeyEqual, typename Allocator>
  98. constexpr bool is_py_map_like_v<std::unordered_map<Key, T, Hash, KeyEqual, Allocator>> = true;
  99. template <typename T>
  100. struct type_caster<T, std::enable_if_t<is_py_map_like_v<T>>> {
  101. T data;
  102. template <typename U>
  103. static object cast(U&& src, return_value_policy policy, handle parent) {
  104. auto dict = pkbind::dict();
  105. for(auto&& [key, value]: src) {
  106. dict[pkbind::cast(std::move(key), policy, parent)] =
  107. pkbind::cast(std::move(value), policy, parent);
  108. }
  109. return dict;
  110. }
  111. bool load(handle src, bool convert) {
  112. if(!isinstance<dict>(src)) { return false; }
  113. auto dict = src.cast<pkbind::dict>();
  114. for(auto item: dict) {
  115. type_caster<typename T::key_type> key_caster;
  116. if(!key_caster.load(item.first, convert)) { return false; }
  117. type_caster<typename T::mapped_type> value_caster;
  118. if(!value_caster.load(item.second, convert)) { return false; }
  119. data.try_emplace(std::move(key_caster.value()), std::move(value_caster.value()));
  120. }
  121. return true;
  122. }
  123. T& value() { return data; }
  124. constexpr inline static bool is_temporary_v = true;
  125. };
  126. } // namespace pkbind