Line data Source code
1 : // SPDX-License-Identifier: BSD-3-Clause 2 : // Copyright (c) 2023 Scipp contributors (https://github.com/scipp) 3 : /// @file 4 : /// @author Simon Heybrock 5 : #pragma once 6 : 7 : #include "scipp/dataset/dataset.h" 8 : 9 : namespace scipp::dataset { 10 : 11 4 : [[noreturn]] inline void throw_nesting_error(const DataArray &) { 12 4 : throw std::invalid_argument("Cannot assign DataArray, the right hand side " 13 : "contains a reference to the left hand side. " 14 8 : "Reference cycles are not allowed."); 15 : } 16 : 17 2 : [[noreturn]] inline void throw_nesting_error(const Dataset &) { 18 2 : throw std::invalid_argument("Cannot assign Dataset, the right hand side " 19 : "contains a reference to the left hand side. " 20 4 : "Reference cycles are not allowed."); 21 : } 22 : 23 : template <class L, class R> 24 : void check_nested_in_assign(const L &lhs, const R &rhs); 25 : 26 : template <class T> 27 50445 : void check_nested_in_assign(const T &lhs, const Variable &rhs) { 28 50445 : if (rhs.dtype() == dtype<DataArray>) { 29 12 : for (const auto &nested : rhs.values<DataArray>()) { 30 4 : check_nested_in_assign(lhs, nested); 31 : } 32 50441 : } else if (rhs.dtype() == dtype<Dataset>) { 33 6 : for (const auto &nested : rhs.values<Dataset>()) { 34 2 : check_nested_in_assign(lhs, nested); 35 : } 36 : } 37 50439 : } 38 : 39 : template <class T, class Key, class Value> 40 145825 : void check_nested_in_assign(const T &lhs, const SizedDict<Key, Value> &rhs) { 41 147716 : for (const auto &[_, var] : rhs) { 42 1895 : check_nested_in_assign(lhs, var); 43 : } 44 145821 : } 45 : 46 : template <class L, class R> 47 48526 : void check_nested_in_assign(const L &lhs, const R &rhs) { 48 : if constexpr (std::is_same_v<L, R>) { 49 48526 : if (&lhs == &rhs) { 50 6 : throw_nesting_error(lhs); 51 : } 52 : } 53 : 54 291258 : const auto check_item = [&](const DataArray &item) { 55 48550 : if (!item.is_valid()) { 56 0 : return; 57 : } 58 48550 : check_nested_in_assign(lhs, item.data()); 59 48548 : check_nested_in_assign(lhs, item.coords()); 60 48545 : check_nested_in_assign(lhs, item.masks()); 61 48545 : check_nested_in_assign(lhs, item.attrs()); 62 : }; 63 : 64 : if constexpr (std::is_same_v<std::decay_t<R>, DataArray>) { 65 48332 : check_item(rhs); 66 : } else { 67 406 : for (const auto &item : rhs) { 68 218 : check_item(item); 69 : } 70 187 : check_nested_in_assign(lhs, rhs.coords()); 71 : } 72 48514 : } 73 : 74 : } // namespace scipp::dataset