Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
param_group_projection.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <algorithm>
6#include <span>
7#include <string>
8#include <unordered_map>
9#include <unordered_set>
10#include <vector>
11
12namespace pulp::format {
13
17 public:
18 struct Entry {
19 int id = 0;
20 int parent_id = 0;
21 std::string name;
22 std::string path;
23 };
24
25 explicit ParamGroupProjection(std::span<const state::ParamGroup> groups) {
26 std::unordered_map<int, const state::ParamGroup*> by_id;
27 std::unordered_set<int> duplicate_ids;
28 by_id.reserve(groups.size());
29 for (const auto& group : groups) {
30 if (group.id <= 0 || group.name.empty())
31 continue;
32 if (!by_id.emplace(group.id, &group).second)
33 duplicate_ids.insert(group.id);
34 }
35
36 enum class Mark { visiting, valid, invalid };
37 std::unordered_map<int, Mark> marks;
38 std::unordered_map<int, std::string> paths;
39 marks.reserve(by_id.size());
40 paths.reserve(by_id.size());
41
42 const auto validate = [&](const auto& self, int id) -> bool {
43 if (duplicate_ids.contains(id))
44 return false;
45 if (const auto mark = marks.find(id); mark != marks.end()) {
46 if (mark->second == Mark::valid)
47 return true;
48 return false;
49 }
50 const auto found = by_id.find(id);
51 if (found == by_id.end())
52 return false;
53 marks[id] = Mark::visiting;
54 const auto& group = *found->second;
55 std::string path;
56 if (group.parent_id == 0) {
57 path = group.name;
58 } else {
59 const auto parent_mark = marks.find(group.parent_id);
60 if ((parent_mark != marks.end() && parent_mark->second == Mark::visiting) ||
61 !self(self, group.parent_id)) {
62 marks[id] = Mark::invalid;
63 return false;
64 }
65 path = paths[group.parent_id] + "/" + group.name;
66 }
67 paths[id] = std::move(path);
68 marks[id] = Mark::valid;
69 return true;
70 };
71
72 std::unordered_set<int> emitted;
73 entries_.reserve(groups.size());
74 emitted.reserve(groups.size());
75 // Keep registration order among siblings while ensuring every parent
76 // precedes its children in host flat-list enumeration.
77 bool made_progress = true;
78 while (made_progress) {
79 made_progress = false;
80 for (const auto& group : groups) {
81 if (!validate(validate, group.id))
82 continue;
83 if (emitted.contains(group.id))
84 continue;
85 if (group.parent_id != 0 && !emitted.contains(group.parent_id))
86 continue;
87 entries_.push_back({group.id, group.parent_id, group.name, paths[group.id]});
88 emitted.insert(group.id);
89 made_progress = true;
90 }
91 }
92 }
93
94 std::span<const Entry> entries() const noexcept {
95 return entries_;
96 }
97
98 const Entry* find(int id) const noexcept {
99 const auto found = std::find_if(entries_.begin(), entries_.end(),
100 [id](const Entry& entry) { return entry.id == id; });
101 return found == entries_.end() ? nullptr : &*found;
102 }
103
104 private:
105 std::vector<Entry> entries_;
106};
107
108} // namespace pulp::format
std::span< const Entry > entries() const noexcept
Definition param_group_projection.hpp:94
ParamGroupProjection(std::span< const state::ParamGroup > groups)
Definition param_group_projection.hpp:25
const Entry * find(int id) const noexcept
Definition param_group_projection.hpp:98
What the product grants a device: the quota table indexed by capability tier and live thermal state.
Definition aax_editor.hpp:31
Definition param_group_projection.hpp:18
std::string name
Definition param_group_projection.hpp:21
int parent_id
Definition param_group_projection.hpp:20
std::string path
Definition param_group_projection.hpp:22