accessor.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #pragma once
  2. #include "builtins.h"
  3. namespace pybind11 {
  4. // implement iterator methods for interface
  5. template <typename Derived>
  6. inline iterator interface<Derived>::begin() const {
  7. return handle(vm->py_iter(this->ptr()));
  8. }
  9. template <typename Derived>
  10. inline iterator interface<Derived>::end() const {
  11. return iterator::sentinel();
  12. }
  13. template <typename Derived>
  14. inline str interface<Derived>::package() const {
  15. return handle(this->attr(pkpy::__package__));
  16. }
  17. template <typename Derived>
  18. inline str interface<Derived>::name() const {
  19. return handle(this->attr(pkpy::__name__));
  20. }
  21. template <typename Derived>
  22. inline str interface<Derived>::repr() const {
  23. return handle(str(vm->py_repr(this->ptr())));
  24. }
  25. template <typename policy>
  26. class accessor : public interface<accessor<policy>> {
  27. using key_type = typename policy::key_type;
  28. handle m_obj;
  29. mutable handle m_value;
  30. key_type m_key;
  31. friend interface<handle>;
  32. friend interface<accessor<policy>>;
  33. friend tuple;
  34. friend list;
  35. friend dict;
  36. accessor(const handle& obj, key_type key) : m_obj(obj), m_value(), m_key(key) {}
  37. public:
  38. pkpy::PyVar ptr() const {
  39. if(!m_value) { m_value = policy::get(m_obj, m_key); }
  40. return m_value.ptr();
  41. }
  42. template <typename Value>
  43. accessor& operator= (Value&& value) && {
  44. policy::set(m_obj, m_key, pybind11::cast(std::forward<Value>(value)));
  45. return *this;
  46. }
  47. template <typename Value>
  48. accessor& operator= (Value&& value) & {
  49. m_value = std::forward<Value>(value);
  50. return *this;
  51. }
  52. template <typename T>
  53. T cast() const {
  54. return operator handle ().template cast<T>();
  55. }
  56. operator handle () const { return ptr(); }
  57. };
  58. namespace policy {
  59. struct attr {
  60. using key_type = pkpy::StrName;
  61. static handle get(const handle& obj, pkpy::StrName key) { return vm->getattr(obj.ptr(), key); }
  62. static void set(const handle& obj, pkpy::StrName key, const handle& value) {
  63. vm->setattr(obj.ptr(), key, value.ptr());
  64. }
  65. };
  66. struct item {
  67. using key_type = handle;
  68. static handle get(const handle& obj, const handle& key) {
  69. return vm->call(vm->py_op("getitem"), obj.ptr(), key.ptr());
  70. }
  71. static void set(const handle& obj, const handle& key, const handle& value) {
  72. vm->call(vm->py_op("setitem"), obj.ptr(), key.ptr(), value.ptr());
  73. }
  74. };
  75. struct tuple {
  76. using key_type = int;
  77. static handle get(const handle& obj, int key) { return obj._as<pkpy::Tuple>()[key]; }
  78. static void set(const handle& obj, size_t key, const handle& value) { obj._as<pkpy::Tuple>()[key] = value.ptr(); }
  79. };
  80. struct list {
  81. using key_type = int;
  82. static handle get(const handle& obj, size_t key) { return obj._as<pkpy::List>()[key]; }
  83. static void set(const handle& obj, size_t key, const handle& value) { obj._as<pkpy::List>()[key] = value.ptr(); }
  84. };
  85. struct dict {
  86. using key_type = handle;
  87. static handle get(const handle& obj, const handle& key) { return obj.cast<pybind11::dict>().getitem(key); }
  88. static void set(const handle& obj, const handle& key, const handle& value) {
  89. obj.cast<pybind11::dict>().setitem(key, value);
  90. }
  91. };
  92. } // namespace policy
  93. // implement other methods of interface
  94. template <typename Derived>
  95. inline attr_accessor interface<Derived>::attr(pkpy::StrName key) const {
  96. return attr_accessor(this->ptr(), key);
  97. }
  98. template <typename Derived>
  99. inline attr_accessor interface<Derived>::attr(const char* key) const {
  100. return attr_accessor(this->ptr(), pkpy::StrName(key));
  101. }
  102. template <typename Derived>
  103. inline attr_accessor interface<Derived>::attr(const handle& key) const {
  104. return attr_accessor(this->ptr(), pkpy::StrName(key._as<pkpy::Str>()));
  105. }
  106. template <typename Derived>
  107. inline attr_accessor interface<Derived>::doc() const {
  108. return attr_accessor(this->ptr(), pkpy::StrName("__doc__"));
  109. }
  110. template <typename Derived>
  111. inline item_accessor interface<Derived>::operator[] (int index) const {
  112. return item_accessor(this->ptr(), int_(index));
  113. }
  114. template <typename Derived>
  115. inline item_accessor interface<Derived>::operator[] (const char* key) const {
  116. return item_accessor(this->ptr(), str(key));
  117. }
  118. template <typename Derived>
  119. inline item_accessor interface<Derived>::operator[] (const handle& key) const {
  120. return item_accessor(this->ptr(), key);
  121. }
  122. inline tuple_accessor tuple::operator[] (int i) const { return tuple_accessor(this->ptr(), i); }
  123. inline list_accessor list::operator[] (int i) const { return list_accessor(this->ptr(), i); }
  124. inline dict_accessor dict::operator[] (int index) const { return dict_accessor(this->ptr(), int_(index)); }
  125. inline dict_accessor dict::operator[] (std::string_view key) const { return dict_accessor(this->ptr(), str(key)); }
  126. inline dict_accessor dict::operator[] (const handle& key) const { return dict_accessor(this->ptr(), key); }
  127. } // namespace pybind11