types.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. #pragma once
  2. #include "error.h"
  3. namespace pkbind {
  4. #define PKBIND_TYPE_IMPL(parent, child, expr) \
  5. \
  6. private: \
  7. friend class type; \
  8. static auto type_or_check() { return expr; } \
  9. \
  10. public: \
  11. using parent::parent; \
  12. using parent::operator=; \
  13. child(const object& o) : parent(type::isinstance<child>(o) ? o : type::of<child>()(o)) {} \
  14. child(object&& o) : \
  15. parent(type::isinstance<child>(o) ? std::move(o) : type::of<child>()(std::move(o))) {}
  16. class type : public object {
  17. protected:
  18. template <typename T>
  19. constexpr inline static bool is_check_v =
  20. std::is_invocable_r_v<bool, decltype(T::type_or_check()), handle>;
  21. static auto type_or_check() { return tp_type; }
  22. public:
  23. using object ::object;
  24. using object ::operator=;
  25. // note: type is global instance, so we use ref_t.
  26. explicit type(py_Type type) : object(py_tpobject(type), ref_t{}) {}
  27. py_Type index() const { return py_totype(ptr()); }
  28. const char* name() const { return py_tpname(index()); }
  29. static type of(handle h) { return type(py_typeof(h.ptr())); }
  30. template <typename T>
  31. static type of();
  32. template <typename T>
  33. static bool isinstance(handle obj);
  34. };
  35. class none : public object {
  36. PKBIND_TYPE_IMPL(object, none, tp_NoneType);
  37. // note: none is global instance, so we use ref_t.
  38. none() : object(py_None, ref_t{}) {}
  39. };
  40. class bool_ : public object {
  41. PKBIND_TYPE_IMPL(object, bool_, tp_bool);
  42. // same as none, bool is a singleton.
  43. bool_(bool value) : object(value ? py_True : py_False, ref_t{}) {}
  44. explicit operator bool () { return py_tobool(ptr()); }
  45. };
  46. class int_ : public object {
  47. PKBIND_TYPE_IMPL(object, int_, tp_int);
  48. int_(py_i64 value) : object(alloc_t{}) { py_newint(m_ptr, value); }
  49. explicit operator py_i64 () { return py_toint(ptr()); }
  50. };
  51. class float_ : public object {
  52. PKBIND_TYPE_IMPL(object, float_, tp_float);
  53. float_(py_f64 value) : object(alloc_t{}) { py_newfloat(m_ptr, value); }
  54. explicit operator py_f64 () { return py_tofloat(ptr()); }
  55. };
  56. bool hasattr(handle obj, name name);
  57. class iterable : public object {
  58. PKBIND_TYPE_IMPL(object, iterable, [](handle h) {
  59. return hasattr(h, "__iter__");
  60. });
  61. };
  62. class iterator : public object {
  63. template <typename Dervied>
  64. friend class interface;
  65. iterator() : object(), m_value() {}
  66. iterator(handle h) : object(h, realloc_t{}), m_value() { operator++ (); }
  67. public:
  68. PKBIND_TYPE_IMPL(object, iterator, [](handle h) {
  69. return hasattr(h, "__iter__") && hasattr(h, "__next__");
  70. });
  71. iterator& operator++ () {
  72. int result = raise_call<py_next>(m_ptr);
  73. if(result == 1) {
  74. m_value = object(retv, realloc_t{});
  75. } else if(result == 0) {
  76. m_value = object();
  77. }
  78. return *this;
  79. }
  80. object operator* () const { return m_value; }
  81. friend bool operator== (const iterator& lhs, const iterator& rhs) {
  82. return lhs.m_value.ptr() == rhs.m_value.ptr();
  83. }
  84. friend bool operator!= (const iterator& lhs, const iterator& rhs) { return !(lhs == rhs); }
  85. static iterator sentinel() { return iterator(); }
  86. private:
  87. object m_value;
  88. };
  89. template <typename Dervied>
  90. iterator interface<Dervied>::begin() const {
  91. raise_call<py_iter>(ptr());
  92. return iterator(retv);
  93. }
  94. template <typename Dervied>
  95. iterator interface<Dervied>::end() const {
  96. return iterator::sentinel();
  97. }
  98. class str : public object {
  99. PKBIND_TYPE_IMPL(object, str, tp_str);
  100. str(const char* data, int size) : object(alloc_t{}) { py_newstrn(m_ptr, data, size); }
  101. str(const char* data) : str(data, static_cast<int>(strlen(data))) {}
  102. str(std::string_view s) : str(s.data(), static_cast<int>(s.size())) {}
  103. template <typename... Args>
  104. object format(Args&&... args);
  105. };
  106. class tuple : public object {
  107. PKBIND_TYPE_IMPL(object, tuple, tp_tuple);
  108. tuple(int size) : object(alloc_t{}) { py_newtuple(m_ptr, size); }
  109. tuple(std::initializer_list<handle> args) : tuple(static_cast<int>(args.size())) {
  110. int index = 0;
  111. for(auto& arg: args) {
  112. py_tuple_setitem(m_ptr, index++, arg.ptr());
  113. }
  114. }
  115. tuple_accessor operator[] (int index) const;
  116. int size() const { return py_tuple_len(m_ptr); }
  117. bool empty() const { return size() == 0; }
  118. class iterator {
  119. friend tuple;
  120. iterator(py_Ref ptr, int index) : ptr(ptr), index(index) {}
  121. public:
  122. bool operator== (const iterator& other) const { return index == other.index; }
  123. bool operator!= (const iterator& other) const { return index != other.index; }
  124. iterator& operator++ () {
  125. index++;
  126. return *this;
  127. }
  128. object operator* () const { return borrow(py_tuple_getitem(ptr, index)); }
  129. private:
  130. py_Ref ptr;
  131. int index;
  132. };
  133. iterator begin() const { return iterator(m_ptr, 0); }
  134. iterator end() const { return iterator(m_ptr, size()); }
  135. };
  136. class list : public object {
  137. PKBIND_TYPE_IMPL(object, list, tp_list);
  138. list() : object(alloc_t{}) { py_newlist(m_ptr); }
  139. list(int size) : object(alloc_t{}) { py_newlistn(m_ptr, size); }
  140. list(std::initializer_list<handle> args) : list(static_cast<int>(args.size())) {
  141. int index = 0;
  142. for(auto& arg: args) {
  143. py_list_setitem(m_ptr, index++, arg.ptr());
  144. }
  145. }
  146. list_accessor operator[] (int index) const;
  147. int size() const { return py_list_len(m_ptr); }
  148. bool empty() const { return size() == 0; }
  149. void swap(int i, int j) { py_list_swap(m_ptr, i, j); }
  150. void append(handle item) { py_list_append(m_ptr, item.ptr()); }
  151. void insert(int index, handle item) { py_list_insert(m_ptr, index, item.ptr()); }
  152. void remove(int index) { py_list_delitem(m_ptr, index); }
  153. void clear() { py_list_clear(m_ptr); }
  154. class iterator {
  155. friend list;
  156. iterator(py_Ref ptr, int index) : ptr(ptr), index(index) {}
  157. public:
  158. iterator(const iterator&) = default;
  159. bool operator== (const iterator& other) const { return index == other.index; }
  160. bool operator!= (const iterator& other) const { return index != other.index; }
  161. iterator operator++ () {
  162. index++;
  163. return *this;
  164. }
  165. object operator* () const { return borrow(py_list_getitem(ptr, index)); }
  166. private:
  167. py_Ref ptr;
  168. int index;
  169. };
  170. iterator begin() const { return iterator(m_ptr, 0); }
  171. iterator end() const { return iterator(m_ptr, size()); }
  172. };
  173. class dict : public object {
  174. PKBIND_TYPE_IMPL(object, dict, tp_dict);
  175. dict() : object(alloc_t{}) { py_newdict(m_ptr); }
  176. dict(std::initializer_list<arg_with_default> args);
  177. dict_accessor<int> operator[] (int key) const;
  178. dict_accessor<name> operator[] (name key) const;
  179. dict_accessor<handle> operator[] (handle key) const;
  180. int size() const { return py_dict_len(m_ptr); }
  181. bool empty() const { return size() == 0; }
  182. template <typename Fn>
  183. void apply(Fn&& fn) {
  184. static_assert(std::is_invocable_v<Fn, py_Ref, py_Ref>);
  185. using ret = std::invoke_result_t<Fn, py_Ref, py_Ref>;
  186. auto callback = +[](py_Ref key, py_Ref value, void* data) -> bool {
  187. auto fn = reinterpret_cast<Fn*>(data);
  188. if constexpr(std::is_same_v<ret, void>) {
  189. (*fn)(key, value);
  190. return true;
  191. } else {
  192. return (*fn)(key, value);
  193. }
  194. };
  195. raise_call<py_dict_apply>(m_ptr, callback, &fn);
  196. }
  197. class iterator {
  198. friend dict;
  199. iterator() : iter(pkbind::iterator::sentinel()) {}
  200. iterator(handle ptr);
  201. public:
  202. iterator(const iterator&) = default;
  203. bool operator== (const iterator& other) const { return iter == other.iter; }
  204. bool operator!= (const iterator& other) const { return !(*this == other); }
  205. iterator operator++ () {
  206. ++iter;
  207. return *this;
  208. }
  209. std::pair<object, object> operator* () const;
  210. private:
  211. object items;
  212. pkbind::iterator iter;
  213. };
  214. iterator begin() const { return iterator(m_ptr); }
  215. iterator end() const { return iterator(); }
  216. };
  217. class slice : public object {
  218. PKBIND_TYPE_IMPL(object, slice, tp_slice);
  219. };
  220. class set : public object {};
  221. class args : public tuple {
  222. PKBIND_TYPE_IMPL(tuple, args, tp_tuple);
  223. };
  224. class kwargs : public dict {
  225. PKBIND_TYPE_IMPL(dict, kwargs, tp_dict);
  226. };
  227. // TODO:
  228. class capsule : public object {
  229. struct capsule_impl {
  230. void* data;
  231. void (*destructor)(void*);
  232. };
  233. inline static py_Type m_type = 0;
  234. PKBIND_TYPE_IMPL(object, capsule, m_type);
  235. static void register_() {
  236. m_type = py_newtype("capsule", tp_object, nullptr, [](void* data) {
  237. auto impl = static_cast<capsule_impl*>(data);
  238. if(impl->data && impl->destructor) { impl->destructor(impl->data); }
  239. });
  240. }
  241. capsule(void* data, void (*destructor)(void*) = nullptr) : object(alloc_t{}) {
  242. void* impl = py_newobject(m_ptr, m_type, 0, sizeof(capsule_impl));
  243. new (impl) capsule_impl{data, destructor};
  244. }
  245. void* data() { return static_cast<capsule_impl*>(py_touserdata(m_ptr))->data; }
  246. template <typename T>
  247. T& cast() {
  248. return *static_cast<T*>(data());
  249. }
  250. };
  251. } // namespace pkbind