Lagrange
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 {
39 return m_data.size();
40 }
41
42 bool has(const std::string& name) const { return m_data.find(name) != m_data.end(); }
43
44 void add(const std::string& name) { m_data.emplace(name, std::make_unique<Attribute>()); }
45
46 template <typename Derived>
47 void add(const std::string& name, Derived&& values)
48 {
49 auto attr = std::make_unique<Attribute>(std::forward<Derived>(values));
50 m_data.emplace(name, std::move(attr));
51 }
52
53 template <typename Derived>
54 void set(const std::string& name, Derived&& values)
55 {
56 auto itr = m_data.find(name);
57 la_runtime_assert(itr != m_data.end(), "Attribute " + name + " does not exist.");
58 if (itr->second == nullptr) {
59 auto attr = std::make_unique<Attribute>();
60 attr->set(std::forward<Derived>(values));
61 itr->second = std::move(attr);
62 } else {
63 itr->second->set(std::forward<Derived>(values));
64 }
65 }
66
67 Attribute* get(const std::string& name)
68 {
69 auto itr = m_data.find(name);
70 la_runtime_assert(itr != m_data.end(), "Attribute " + name + " does not exist.");
71 return itr->second.get();
72 }
73
74 const Attribute* get(const std::string& name) const
75 {
76 auto itr = m_data.find(name);
77 la_runtime_assert(itr != m_data.end(), "Attribute " + name + " does not exist.");
78 return itr->second.get();
79 }
80
81 template <typename Derived>
82 decltype(auto) get(const std::string& name)
83 {
84 auto ptr = get(name);
85 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
86 return ptr->get<Derived>();
87 }
88
89 template <typename Derived>
90 decltype(auto) get(const std::string& name) const
91 {
92 const auto ptr = get(name);
93 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
94 return ptr->get<Derived>();
95 }
96
97 template <typename Derived>
98 decltype(auto) view(const std::string& name)
99 {
100 auto ptr = get(name);
101 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
102 return ptr->view<Derived>();
103 }
104
105 template <typename Derived>
106 decltype(auto) view(const std::string& name) const
107 {
108 const auto ptr = get(name);
109 la_runtime_assert(ptr != nullptr, "Attribute " + name + " is null.");
110 return ptr->view<Derived>();
111 }
112
113 template <typename Derived>
114 void import_data(const std::string& name, Derived&& values)
115 {
116 set(name, std::move(values.derived()));
117 }
118
119 template <typename Derived>
120 void export_data(const std::string& name, Eigen::PlainObjectBase<Derived>& values)
121 {
122 auto attr = get(name);
123 la_runtime_assert(attr != nullptr, "Attribute " + name + " is null.");
124 auto value_array = attr->get();
125
126#ifndef NDEBUG
127 bool validate = true;
128 void* value_ptr = value_array->data();
129#endif
130 try {
131 Derived& value_matrix = value_array->template get<Derived>();
132 values.swap(value_matrix);
133 } catch (std::runtime_error& e) {
134 // It seems Derived is not an exact match to the
135 // Eigen type used for creating the attribute. A copy is necessary.
136 logger().warn("Export cannot be done without coping: {}", e.what());
137 values = value_array->view<Derived>();
138#ifndef NDEBUG
139 validate = false;
140#endif
141 }
142
143#ifndef NDEBUG
144 if (validate) {
145 la_runtime_assert(value_ptr == values.data(), "Export have to fall back to copying.");
146 }
147#endif
148 }
149
150 void remove(const std::string& name)
151 {
152 auto itr = m_data.find(name);
153 la_runtime_assert(itr != m_data.end(), "Attribute " + name + " does not exist.");
154 m_data.erase(itr);
155 }
156
157 template <typename Archive>
158 void serialize_impl(Archive& ar)
159 {
161 enum { DATA = 0 };
162 ar.object([&](auto& ar) {
163 ar("data", DATA) & m_data;
164 });
165 LA_IGNORE_SHADOW_WARNING_END
166 }
167
168private:
169 std::map<std::string, std::unique_ptr<Attribute>> m_data;
170};
171
173
174template <typename Archive>
175void serialize(std::pair<std::string, Attribute>& entry, Archive& ar)
176{
177 enum { KEY = 0, VALUE = 1 };
178
179 ar.object([&](auto& ar) {
180 ar("key", KEY) & entry.first;
181 ar("value", VALUE) & entry.second;
182 });
183}
184
185template <typename Archive>
186void serialize(
187 std::map<std::string, std::unique_ptr<Attribute>>& attrs,
188 Archive& ar)
189{
190 std::vector<std::pair<std::string, Attribute>> data;
191 if (!ar.is_input()) {
192 for (auto& itr : attrs) {
193 data.emplace_back(itr.first, *itr.second);
194 }
195 }
196
197 serialize(data, ar);
198
199 if (ar.is_input()) {
200 attrs.clear();
201 for (const auto& itr : data) {
202 attrs[itr.first] = std::make_unique<Attribute>(itr.second);
203 }
204 }
205}
206
207template <typename Archive>
208void serialize(AttributeManager& attributes, Archive& ar)
209{
210 attributes.serialize_impl(ar);
211}
212
213LA_IGNORE_SHADOW_WARNING_END
214
215} // namespace experimental
216} // 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:169
#define LA_IGNORE_SHADOW_WARNING_BEGIN
Ignore shadow warnings.
Definition: warning.h:68
Main namespace for Lagrange.
Definition: AABBIGL.h:30