list.h 4.7 KB

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