123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- /*
- * abstract_node.cpp - abstract Node
- * Copyright (C) 2017 caryoscelus
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <core/node/abstract_node.h>
- #include <core/node/abstract_value.h>
- namespace rainynite::core {
- AbstractNode::~AbstractNode() {
- for (auto const& connection : signal_connections) {
- connection.disconnect();
- }
- }
- AbstractReference AbstractNode::get_property(string const& name) const {
- auto result = named_storage.find(name);
- if (result == named_storage.end())
- throw NodeAccessError("Unknown property "+name);
- return get_by_id(result->second);
- }
- void AbstractNode::set_property(string const& name, AbstractReference ref) {
- if (named_storage.count(name) == 0) {
- if (name[0] == '_') {
- // accept as custom attribute
- init_property(name, {}, ref);
- } else
- throw NodeAccessError("No such property");
- }
- set_link(named_storage[name], ref);
- }
- bool AbstractNode::remove_property(string const& name) {
- if (name[0] != '_')
- return false; // can only remove custom props
- auto iter = named_storage.find(name);
- if (iter == std::end(named_storage))
- return false;
- auto i = iter->second;
- // NOTE: this might be not thread-safe
- named_storage.erase(iter);
- names_list.erase(names_list.begin()+i);
- numbered_storage.erase(numbered_storage.begin()+i);
- // reassign links
- for (auto& e : named_storage) {
- if (e.second > i)
- --e.second;
- }
- return true;
- }
- size_t AbstractNode::init_property(string const& name, optional<Type> type, AbstractReference value) {
- size_t id = link_count();
- numbered_storage.push_back(value);
- names_list.push_back(name);
- named_storage[name] = id;
- types.push_back(type);
- boost::signals2::connection connection;
- if (value)
- connection = value->subscribe([this]() {
- node_changed();
- });
- signal_connections.push_back(connection);
- return id;
- }
- map<string, AbstractReference> AbstractNode::get_link_map() const {
- map<string, AbstractReference> result;
- // TODO: use generic conversion function
- for (auto const& e : named_storage) {
- result.emplace(e.first, get_by_id(e.second));
- }
- return result;
- }
- void AbstractNode::set_link(size_t i, AbstractReference value) {
- if (auto type = get_link_type(i)) {
- if (value->get_type() != *type)
- throw NodeAccessError("Node property type mis-match");
- }
- signal_connections[i].disconnect();
- get_by_id(i) = value;
- signal_connections[i] = value->subscribe([this]() {
- node_changed();
- });
- node_changed();
- }
- } // namespace rainynite::core
|