Lagrange
Loading...
Searching...
No Matches
AttributeManager.h
1/*
2 * Copyright 2020 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12#pragma once
13
14#include <map>
15#include <string>
16
17#include <lagrange/Logger.h>
18#include <lagrange/common.h>
19#include <lagrange/experimental/Attribute.h>
20#include <lagrange/utils/assert.h>
21#include <lagrange/utils/warning.h>
22
23namespace lagrange {
24namespace experimental {
25
27{
28public:
29 std::vector<std::string> get_names() const
30 {
31 std::vector<std::string> names;
32 for (const auto& itr : m_data) {
33 names.push_back(itr.first);
34 }
35 return names;
36 }
37
38 size_t get_size() const { return m_data.size(); }
39
40 bool has(const std::string& name) const { return m_data.find(name) != m_data.end(); }
41
42 void add(const std::string& name) { m_data.emplace(name, std::make_unique<Attribute>()); }
43
44 template <typename Derived>
45 void add(const std::string& name, Derived&& values)
46 {
47 auto attr = std::make_unique<Attribute>(std::forward<Derived>(values));
48 m_data.emplace(name, std::move(attr));
49 }
50
51 template <typename Derived>
52 void set(const std::string& name, Derived&& values)
53 {
54 auto itr = m_data.find(name);
55 la_runtime_assert(itr != m_data.end(), "Attribute " + name + " does not exist.");
56 if (itr->second == nullptr) {
57 auto attr = std::make_unique<Attribute>();
58 attr->set(std::forward<Derived>(values));
59 itr->second = std::move(attr);
60 } else {
61 itr->second->set(std::forward<Derived>(values));
62 }
63 }
64
65 Attribute* get(const std::string& name)
66 {
67 auto itr = m_data.find(name);
68 la_runtime_assert(itr != m_data.end(), "Attribute " + name + " does not exist.");
69 return itr->second.get();
70 }
71
72 const Attribute* get(const std::string& name) const
73 {
74 auto itr = m_data.find(name);
75 la_runtime_assert(itr != m_data.end(), "Attribute " + name + " does not exist.");
76 return itr->second.get();
77 }
78
79 template <typename Derived>
80 decltype(auto) get(const std::string& name)
81 {
82 auto ptr = get(name);
83 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
84 return ptr->get<Derived>();
85 }
86
87 template <typename Derived>
88 decltype(auto) get(const std::string& name) const
89 {
90 const auto ptr = get(name);
91 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
92 return ptr->get<Derived>();
93 }
94
95 template <typename Derived>
96 decltype(auto) view(const std::string& name)
97 {
98 auto ptr = get(name);
99 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
100 return ptr->view<Derived>();
101 }
102
103 template <typename Derived>
104 decltype(auto) view(const std::string& name) const
105 {
106 const auto ptr = get(name);
107 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
108 return ptr->view<Derived>();
109 }
110
111 template <typename Derived>
112 void import_data(const std::string& name, Derived&& values)
113 {
114 set(name, std::move(values.derived()));
115 }
116
117 template <typename Derived>
118 void export_data(const std::string& name, Eigen::PlainObjectBase<Derived>& values)
119 {
120 auto attr = get(name);
121 la_runtime_assert(attr != nullptr, "Attribute " + name + " is null.");
122 auto value_array = attr->get();
123
124#ifndef NDEBUG
125 bool validate = true;
126 void* value_ptr = value_array->data();
127#endif
128 try {
129 Derived& value_matrix = value_array->template get<Derived>();
130 values.swap(value_matrix);
131 } catch (std::runtime_error& e) {
132 // It seems Derived is not an exact match to the
133 // Eigen type used for creating the attribute. A copy is necessary.
134 logger().warn("Export cannot be done without coping: {}", e.what());
135 values = value_array->view<Derived>();
136#ifndef NDEBUG
137 validate = false;
138#endif
139 }
140
141#ifndef NDEBUG
142 if (validate) {
143 la_runtime_assert(value_ptr == values.data(), "Export have to fall back to copying.");
144 }
145#endif
146 }
147
148 void remove(const std::string& name)
149 {
150 auto itr = m_data.find(name);
151 la_runtime_assert(itr != m_data.end(), "Attribute " + name + " does not exist.");
152 m_data.erase(itr);
153 }
154
155 template <typename Archive>
156 void serialize_impl(Archive& ar)
157 {
159 enum { DATA = 0 };
160 ar.object([&](auto& ar) { ar("data", DATA) & m_data; });
161 LA_IGNORE_SHADOW_WARNING_END
162 }
163
164private:
165 std::map<std::string, std::unique_ptr<Attribute>> m_data;
166};
167
169
170template <typename Archive>
171void serialize(std::pair<std::string, Attribute>& entry, Archive& ar)
172{
173 enum { KEY = 0, VALUE = 1 };
174
175 ar.object([&](auto& ar) {
176 ar("key", KEY) & entry.first;
177 ar("value", VALUE) & entry.second;
178 });
179}
180
181template <typename Archive>
182void serialize(std::map<std::string, std::unique_ptr<Attribute>>& attrs, Archive& ar)
183{
184 std::vector<std::pair<std::string, Attribute>> data;
185 if (!ar.is_input()) {
186 for (auto& itr : attrs) {
187 data.emplace_back(itr.first, *itr.second);
188 }
189 }
190
191 serialize(data, ar);
192
193 if (ar.is_input()) {
194 attrs.clear();
195 for (const auto& itr : data) {
196 attrs[itr.first] = std::make_unique<Attribute>(itr.second);
197 }
198 }
199}
200
201template <typename Archive>
202void serialize(AttributeManager& attributes, Archive& ar)
203{
204 attributes.serialize_impl(ar);
205}
206
207LA_IGNORE_SHADOW_WARNING_END
208
209} // namespace experimental
210} // namespace lagrange
Definition Attribute.h:23
Definition AttributeManager.h:27
Smart pointer with value semantics.
Definition value_ptr.h:134
LA_CORE_API spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:40
#define la_runtime_assert(...)
Runtime assertion check.
Definition assert.h:174
#define LA_IGNORE_SHADOW_WARNING_BEGIN
Ignore shadow warnings.
Definition warning.h:68
Main namespace for Lagrange.