tuplelist.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #pragma once
  2. #include "common.h"
  3. #include "memory.h"
  4. #include "str.h"
  5. namespace pkpy {
  6. class List: public std::vector<PyVar> {
  7. PyVar& at(size_t) = delete;
  8. inline void _check_index(size_t i) const {
  9. if (i >= size()){
  10. auto msg = "std::vector index out of range, " + std::to_string(i) + " not in [0, " + std::to_string(size()) + ")";
  11. throw std::out_of_range(msg);
  12. }
  13. }
  14. public:
  15. PyVar& operator[](size_t i) {
  16. _check_index(i);
  17. return std::vector<PyVar>::operator[](i);
  18. }
  19. const PyVar& operator[](size_t i) const {
  20. _check_index(i);
  21. return std::vector<PyVar>::operator[](i);
  22. }
  23. using std::vector<PyVar>::vector;
  24. };
  25. class Args {
  26. static THREAD_LOCAL SmallArrayPool<PyVar, 10> _pool;
  27. PyVar* _args;
  28. int _size;
  29. inline void _alloc(int n){
  30. this->_args = _pool.alloc(n);
  31. this->_size = n;
  32. }
  33. public:
  34. Args(int n){ _alloc(n); }
  35. Args(const Args& other){
  36. _alloc(other._size);
  37. for(int i=0; i<_size; i++) _args[i] = other._args[i];
  38. }
  39. Args(std::initializer_list<PyVar> a){
  40. _alloc(a.size());
  41. int i = 0;
  42. for(auto& v: a) _args[i++] = v;
  43. }
  44. Args(Args&& other) noexcept {
  45. this->_args = other._args;
  46. this->_size = other._size;
  47. other._args = nullptr;
  48. other._size = 0;
  49. }
  50. Args(pkpy::List&& other) noexcept {
  51. _alloc(other.size());
  52. memcpy((void*)_args, (void*)other.data(), sizeof(PyVar)*_size);
  53. memset((void*)other.data(), 0, sizeof(PyVar)*_size);
  54. other.clear();
  55. }
  56. PyVar& operator[](int i){ return _args[i]; }
  57. const PyVar& operator[](int i) const { return _args[i]; }
  58. Args& operator=(Args&& other) noexcept {
  59. _pool.dealloc(_args, _size);
  60. this->_args = other._args;
  61. this->_size = other._size;
  62. other._args = nullptr;
  63. other._size = 0;
  64. return *this;
  65. }
  66. inline int size() const { return _size; }
  67. pkpy::List move_to_list() noexcept {
  68. pkpy::List ret(_size);
  69. memcpy((void*)ret.data(), (void*)_args, sizeof(PyVar)*_size);
  70. memset((void*)_args, 0, sizeof(PyVar)*_size);
  71. return ret;
  72. }
  73. void extend_self(const PyVar& self){
  74. static_assert(std::is_standard_layout_v<PyVar>);
  75. PyVar* old_args = _args;
  76. int old_size = _size;
  77. _alloc(old_size+1);
  78. _args[0] = self;
  79. if(old_size == 0) return;
  80. memcpy((void*)(_args+1), (void*)old_args, sizeof(PyVar)*old_size);
  81. memset((void*)old_args, 0, sizeof(PyVar)*old_size);
  82. _pool.dealloc(old_args, old_size);
  83. }
  84. ~Args(){ _pool.dealloc(_args, _size); }
  85. };
  86. static const Args _zero(0);
  87. inline const Args& no_arg() { return _zero; }
  88. template<typename T>
  89. Args one_arg(T&& a) {
  90. Args ret(1);
  91. ret[0] = std::forward<T>(a);
  92. return ret;
  93. }
  94. template<typename T1, typename T2>
  95. Args two_args(T1&& a, T2&& b) {
  96. Args ret(2);
  97. ret[0] = std::forward<T1>(a);
  98. ret[1] = std::forward<T2>(b);
  99. return ret;
  100. }
  101. typedef Args Tuple;
  102. THREAD_LOCAL SmallArrayPool<PyVar, 10> Args::_pool;
  103. } // namespace pkpy