list.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /* list.h - list
  2. * Copyright (C) 2017 caryoscelus
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #ifndef CORE_NODE_LIST_H_12D92F7F_8F30_5447_9F54_AFB006578F3D
  18. #define CORE_NODE_LIST_H_12D92F7F_8F30_5447_9F54_AFB006578F3D
  19. #include <core/std/traits.h>
  20. #include <core/nothing.h>
  21. #include "abstract_list.h"
  22. #include "abstract_value.h"
  23. #include "make.h"
  24. namespace rainynite::core {
  25. template <typename T, typename P>
  26. void push_value(P list, T const& value) {
  27. list->push_back(make_value<T>(value));
  28. }
  29. /**
  30. * Base template for typed and mixed lists
  31. */
  32. template <class S, class P>
  33. class ListValueBase : public AbstractListLinked, public P {
  34. public:
  35. vector<AbstractReference> get_links() const override {
  36. if constexpr (is_same_v<S, AbstractValue>)
  37. return values;
  38. vector<AbstractReference> result;
  39. std::transform(
  40. values.begin(),
  41. values.end(),
  42. std::back_inserter(result),
  43. [](auto e) {
  44. return e;
  45. }
  46. );
  47. return result;
  48. }
  49. protected:
  50. vector<NodeInContext> get_list_links(shared_ptr<Context> context) const override {
  51. vector<NodeInContext> result;
  52. std::transform(
  53. values.begin(),
  54. values.end(),
  55. std::back_inserter(result),
  56. [context](auto&& e) {
  57. return NodeInContext(e, context);
  58. }
  59. );
  60. return result;
  61. }
  62. public:
  63. AbstractReference get_link(size_t i) const override {
  64. return values.at(i);
  65. }
  66. size_t link_count() const override {
  67. return values.size();
  68. }
  69. void set_link(size_t i, AbstractReference value) override {
  70. if (auto node = dynamic_pointer_cast<S>(std::move(value))) {
  71. values.at(i) = node;
  72. signal_connections[i].disconnect();
  73. signal_connections[i] = node->subscribe([this]() {
  74. this->changed();
  75. });
  76. this->changed();
  77. }
  78. }
  79. void push_back(AbstractReference value) override {
  80. insert(link_count(), value);
  81. }
  82. void push_new() override {
  83. push_value<Nothing>(this, {});
  84. }
  85. void insert(size_t i, AbstractReference value) override {
  86. if (auto e = dynamic_pointer_cast<S>(std::move(value))) {
  87. values.insert(values.begin()+i, e);
  88. signal_connections.insert(
  89. signal_connections.begin()+i,
  90. e->subscribe([this]() {
  91. this->changed();
  92. })
  93. );
  94. this->changed();
  95. } else {
  96. // TODO: throw?
  97. }
  98. }
  99. void remove(size_t index) override {
  100. values.erase(values.begin()+index);
  101. signal_connections.erase(signal_connections.begin()+index);
  102. this->changed();
  103. }
  104. void pop() override {
  105. remove(values.size()-1);
  106. }
  107. bool is_editable_list() const override {
  108. return true;
  109. }
  110. protected:
  111. vector<shared_ptr<S>> values;
  112. vector<boost::signals2::connection> signal_connections;
  113. };
  114. /**
  115. * Typed (homogeneous) list
  116. */
  117. template <typename T>
  118. class ListValue : public ListValueBase<BaseValue<T>, BaseValue<vector<T>>> {
  119. public:
  120. ListValue() = default;
  121. public:
  122. vector<T> get(shared_ptr<Context> context) const override {
  123. // TODO: caching
  124. vector<T> result;
  125. std::transform(
  126. this->values.begin(),
  127. this->values.end(),
  128. std::back_inserter(result),
  129. [context](auto e) {
  130. return e->get(context);
  131. }
  132. );
  133. return result;
  134. }
  135. TypeConstraint get_link_type(size_t) const override {
  136. return {Type(typeid(T))};
  137. }
  138. void push_new() override {
  139. push_value<T>(this, {});
  140. }
  141. };
  142. /**
  143. * Untyped (heterogeneous) list value
  144. */
  145. class UntypedListValue : public ListValueBase<AbstractValue, AbstractValue> {
  146. public:
  147. Type get_type() const override {
  148. return typeid(Nothing);
  149. }
  150. any get_any(shared_ptr<Context> /*context*/) const noexcept override {
  151. return Nothing();
  152. }
  153. TypeConstraint get_link_type(size_t) const override {
  154. return {};
  155. }
  156. public:
  157. static Type static_type() {
  158. return typeid(Nothing);
  159. }
  160. };
  161. } // namespace rainynite::core
  162. #endif