accessor.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. #pragma once
  2. #include "builtins.h"
  3. namespace pkbind {
  4. template <typename policy>
  5. class accessor : public interface<accessor<policy>> {
  6. using key_type = typename policy::key_type;
  7. friend interface<handle>;
  8. friend interface<accessor<policy>>;
  9. friend tuple;
  10. friend list;
  11. friend dict;
  12. accessor(handle obj, key_type key) : m_obj(obj), m_value(), m_key(key) {}
  13. public:
  14. auto ptr() const {
  15. if(m_value.empty()) {
  16. m_value = borrow(policy::get(m_obj, m_key));
  17. }
  18. return m_value.ptr();
  19. }
  20. template <typename Value>
  21. accessor& operator= (Value&& value) && {
  22. policy::set(m_obj, m_key, pkbind::cast(std::forward<Value>(value)));
  23. return *this;
  24. }
  25. template <typename Value>
  26. accessor& operator= (Value&& value) & {
  27. m_value = std::forward<Value>(value);
  28. return *this;
  29. }
  30. operator handle () const { return ptr(); }
  31. private:
  32. handle m_obj;
  33. mutable object m_value;
  34. key_type m_key;
  35. };
  36. namespace policy {
  37. struct attr {
  38. using key_type = name;
  39. static handle get(handle obj, name key) {
  40. raise_call<py_getattr>(obj.ptr(), key.index());
  41. return py_retval();
  42. }
  43. static void set(handle obj, name key, handle value) { raise_call<py_setattr>(obj.ptr(), key.index(), value.ptr()); }
  44. };
  45. template <typename Key>
  46. struct item {
  47. using key_type = Key;
  48. static handle get(handle obj, int key) { return get(obj, int_(key)); }
  49. static handle get(handle obj, name key) { return get(obj, str(key)); }
  50. static handle get(handle obj, handle key) {
  51. raise_call<py_getitem>(obj.ptr(), key.ptr());
  52. return py_retval();
  53. }
  54. static void set(handle obj, int key, handle value) { set(obj, int_(key), value); }
  55. static void set(handle obj, name key, handle value) { set(obj, str(key), value); }
  56. static void set(handle obj, handle key, handle value) { raise_call<py_setitem>(obj.ptr(), key.ptr(), value.ptr()); }
  57. };
  58. struct tuple {
  59. using key_type = int;
  60. static handle get(handle obj, int key) { return py_tuple_getitem(obj.ptr(), key); }
  61. static void set(handle obj, int key, handle value) { py_tuple_setitem(obj.ptr(), key, value.ptr()); }
  62. };
  63. struct list {
  64. using key_type = int;
  65. static handle get(handle obj, int key) { return py_list_getitem(obj.ptr(), key); }
  66. static void set(handle obj, int key, handle value) { py_list_setitem(obj.ptr(), key, value.ptr()); }
  67. };
  68. template <typename Key>
  69. struct dict {
  70. using key_type = Key;
  71. static handle get(handle obj, int key) { return get(obj, int_(key)); }
  72. static handle get(handle obj, name key) { return get(obj, str(key)); }
  73. static handle get(handle obj, handle key) {
  74. raise_call<py_dict_getitem>(obj.ptr(), key.ptr());
  75. return py_retval();
  76. }
  77. static void set(handle obj, int key, handle value) { set(obj, int_(key), value); }
  78. static void set(handle obj, name key, handle value) { set(obj, str(key), value); }
  79. static void set(handle obj, handle key, handle value) {
  80. raise_call<py_dict_setitem>(obj.ptr(), key.ptr(), value.ptr());
  81. }
  82. };
  83. } // namespace policy
  84. // implement other methods of interface
  85. template <typename Derived>
  86. inline attr_accessor interface<Derived>::attr(name key) const {
  87. return {ptr(), key};
  88. }
  89. template <typename Derived>
  90. inline item_accessor<int> interface<Derived>::operator[] (int key) const {
  91. return {ptr(), key};
  92. }
  93. template <typename Derived>
  94. inline item_accessor<name> interface<Derived>::operator[] (name key) const {
  95. return {ptr(), key};
  96. }
  97. template <typename Derived>
  98. inline item_accessor<handle> interface<Derived>::operator[] (handle key) const {
  99. return {ptr(), key};
  100. }
  101. template <typename... Args>
  102. object str::format(Args&&... args) {
  103. return attr("format")(std::forward<Args>(args)...);
  104. }
  105. inline tuple_accessor tuple::operator[] (int index) const { return {m_ptr, index}; }
  106. inline list_accessor list::operator[] (int index) const { return {m_ptr, index}; };
  107. inline dict_accessor<int> dict::operator[] (int key) const { return {m_ptr, key}; }
  108. inline dict_accessor<name> dict::operator[] (name key) const { return {m_ptr, key}; }
  109. inline dict_accessor<handle> dict::operator[] (handle key) const { return {m_ptr, key}; }
  110. inline dict::iterator::iterator(handle h) : items(h.attr("items")()), iter(items.begin()) {}
  111. inline std::pair<object, object> dict::iterator::operator* () const {
  112. tuple pair = *iter;
  113. return {borrow(pair[0]), borrow(pair[1])};
  114. }
  115. } // namespace pkbind