Anklang-0.3.0-1416-gfa8ce8d2 anklang-0.3.0-1416-gfa8ce8d2
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
gadget.cc
Go to the documentation of this file.
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2#include "gadget.hh"
3#include "jsonipc/jsonipc.hh"
4#include "strings.hh"
5#include "utils.hh"
6#include "project.hh"
7#include "internal.hh"
8#include "randomhash.hh"
9
10namespace Ase {
11
12// == Gadget ==
13Gadget::Gadget()
14{}
15
16// == GadgetImpl ==
17GadgetImpl::~GadgetImpl()
18{}
19
21GadgetImpl::gadget_flags (uint64_t setbits, uint64_t mask)
22{
23 gadget_flags_ &= mask;
24 gadget_flags_ |= setbits;
25 return gadget_flags_;
26}
27
28void
30{
31 if (parent)
32 assert_return (parent_ == nullptr);
33 else // !parent
34 assert_return (parent_ != nullptr);
35 parent_ = parent;
36}
37
39GadgetImpl::canonify_key (const String &input)
40{
41 String key = string_canonify (input, string_set_a2z() + string_set_A2Z() + "_0123456789.", "_");
42 if (key.size() && key[0] == '.')
43 key = "_" + key;
44 return key;
45}
46
47Value
48GadgetImpl::get_data (const String &key) const
49{
50 const String ckey = canonify_key (key);
51 return session_data_[ckey];
52}
53
54bool
55GadgetImpl::set_data (const String &key, const Value &v)
56{
57 const String ckey = canonify_key (key);
58 return_unless (ckey.size(), false);
59 session_data_[ckey] = v;
60 emit_event ("data", ckey);
61 return true;
62}
63
65GadgetImpl::type_nick () const
66{
67 String tname = Jsonipc::rtti_typename (*this);
68 ssize_t colon = tname.rfind (':');
69 if (colon != ssize_t (tname.npos))
70 tname = tname.substr (colon + 1);
71 if (string_endswith (tname, "Impl"))
72 tname = tname.substr (0, tname.size() - 4);
73 return tname;
74}
75
76PropertyS
78{
79 if (props_.empty())
80 create_properties();
81 return { begin (props_), end (props_) };
82}
83
84// == GadgetImpl ==
85void
87{
88 parent_ = nullptr;
89 emit_event ("object", "removed");
90}
91
92// == Gadget ==
95{
96 Gadget *last = const_cast<Gadget*> (this);
97 for (Gadget *parent = last->_parent(); parent; parent = last->_parent())
98 last = parent;
99 return dynamic_cast<ProjectImpl*> (last);
100}
101
104{
105 return {};
106}
107
110{
111 PropertyS props = access_properties();
112 StringS names;
113 names.reserve (props.size());
114 for (const PropertyP &prop : props)
115 names.push_back (prop->ident());
116 return names;
117}
118
119PropertyP
121{
122 for (const auto &p : access_properties())
123 if (p->ident() == ident)
124 return p;
125 return {};
126}
127
128Value
130{
131 PropertyP prop = access_property (ident);
132 return prop ? prop->value() : Value {};
133}
134
135bool
137{
138 PropertyP prop = access_property (ident);
139 return prop && prop->value (v);
140}
141
143 const char *member_typeid_name = nullptr;
144 ptrdiff_t memb_offset = -1;
146 GadgetImpl::MemberInfosP infosp = nullptr;
148 uint64_t flags = 0;
149};
150
152 /*key*/
153 const char *class_typeid_name = nullptr;
154 /*payload*/
155 GadgetImpl::MemberClassT classtest = nullptr;
157};
158
159static auto&
160cml_set()
161{
162 static auto gcml_hash = [] (const GadgetClassMemberList &m) {
163 return fnv1a_consthash64 (m.class_typeid_name);
164 };
165 static auto gcml_equal = [] (const GadgetClassMemberList &a, const GadgetClassMemberList &b) {
166 return !strcmp (a.class_typeid_name, b.class_typeid_name);
167 };
168 using MemberAccessorSet = std::unordered_set<GadgetClassMemberList, decltype (gcml_hash), decltype (gcml_equal)>;
169 static MemberAccessorSet mas (0, gcml_hash, gcml_equal);
170 return mas;
171}
172
173bool
174GadgetImpl::requires_accessor (const char *ot, const char *mt, ptrdiff_t offset)
175{
176 auto &cml = cml_set();
177 const GadgetClassMemberList key { .class_typeid_name = ot };
178 auto it = cml.find (key);
179 if (it != cml.end())
180 for (const MemberAccessor *maf : it->members)
181 if (!strcmp (mt, maf->member_typeid_name)) {
182 assert_return (maf->memb_offset == offset, false);
183 return false;
184 }
185 return true;
186}
187
188void
189GadgetImpl::register_accessor (const char *ot, const char *mt, ptrdiff_t offset, MemberClassT classtest,
190 const Param::ExtraVals &ev, MemberAccessF &&accessfunc,
191 MemberInfosP infosp, uint64_t flags)
192{
193 auto &cml = cml_set();
194 auto [celement, inserted] = cml.emplace (ot, classtest);
195 assert_return (celement != cml.end());
196 GadgetClassMemberList *element = const_cast<GadgetClassMemberList*> (&*celement);
197 element->members.push_back (new MemberAccessor {mt, offset, std::move (accessfunc), infosp, ev, flags});
198 //printerr ("%s: %s+%s=%+zd\n", __func__, ot, mt, offset);
199}
200
201void
202GadgetImpl::create_properties ()
203{
204 /* When creating the properties for an instance, walk through the known
205 * GadgetClassMemberList entries, test each via dynamic_cast and thus
206 * identify all class member lists that match the instance.
207 */
208 auto &cml = cml_set();
209 for (const GadgetClassMemberList &ml : cml)
210 if (ml.classtest (*this))
211 for (const MemberAccessor *m : ml.members) {
212 PropertyGetter getter = [this,m] (Value &value) { m->func (this, nullptr, &value); };
213 PropertySetter setter = [this,m] (const Value &value) { return m->func (this, &value, nullptr); };
214 PropertyLister lister = nullptr;
215 StringS infos = m->infosp();
216 String hints = kvpairs_fetch (infos, "hints");
217 if (m->flags & MemberDetails::READABLE)
218 hints += ":r";
219 if (m->flags & MemberDetails::WRITABLE)
220 hints += ":w";
221 if (m->flags & MemberDetails::STORAGE)
222 hints += ":S";
223 if (m->flags & MemberDetails::GUI)
224 hints += ":G";
225 kvpairs_assign (infos, "hints=" + hints);
226 Param param { .extras = m->ev, .metadata = infos };
227 this->props_.push_back (PropertyImpl::make_shared (param, getter, setter, lister));
228 }
229}
230
231} // Ase
Base type for classes that have a Property.
Definition gadget.hh:11
void remove_self() override
Remove self from parent container.
Definition gadget.cc:86
PropertyS access_properties() override
Retrieve handles for all properties.
Definition gadget.cc:77
Value get_data(const String &key) const override
Retrieve session data.
Definition gadget.cc:48
bool set_data(const String &key, const Value &v) override
Assign session data, prefix ephemerals with '_'.
Definition gadget.cc:55
void _set_parent(GadgetImpl *parent) override
Assign parent container.
Definition gadget.cc:29
Base type for classes that have a Property.
Definition api.hh:173
virtual StringS list_properties()
List all property identifiers.
Definition gadget.cc:109
virtual PropertyP access_property(String ident)
Retrieve handle for a Property.
Definition gadget.cc:120
virtual PropertyS access_properties()=0
Retrieve handles for all properties.
ProjectImpl * _project() const
Find Project in parent ancestry.
Definition gadget.cc:94
virtual GadgetImpl * _parent() const =0
Retrieve parent container.
virtual StringS read_only_properties() const
List x()/x (v) properties that this object can't change, their setters ignore the value or warn.
Definition gadget.cc:103
Value get_value(String ident)
Get native property value.
Definition gadget.cc:129
bool set_value(String ident, const Value &v)
Set native property value.
Definition gadget.cc:136
T find(T... args)
#define assert_return(expr,...)
Return from the current function if expr is unmet and issue an assertion warning.
Definition internal.hh:28
#define return_unless(cond,...)
Return silently if cond does not evaluate to true with return value ...
Definition internal.hh:72
The Anklang C++ API namespace.
Definition api.hh:8
std::vector< String > StringS
Convenience alias for a std::vector<std::string>.
Definition cxxaux.hh:35
std::function< ChoiceS(const ParameterProperty &)> PropertyLister
Function type to list Choice Property values.
Definition properties.hh:75
const String & string_set_a2z()
Returns a string containing all of a-z.
Definition strings.cc:102
std::string String
Convenience alias for std::string.
Definition cxxaux.hh:34
String string_canonify(const String &string, const String &valid_chars, const String &substitute)
Enforce a canonical charset for a string.
Definition strings.cc:68
const String & string_set_A2Z()
Returns a string containing all of A-Z.
Definition strings.cc:110
std::function< void(Value &)> PropertyGetter
Function type for Property value getters.
Definition properties.hh:69
bool string_endswith(const String &string, const String &fragment)
Returns whether string ends with fragment.
Definition strings.cc:863
std::function< bool(const Value &)> PropertySetter
Function type for Property value setters.
Definition properties.hh:72
T push_back(T... args)
T reserve(T... args)
T rfind(T... args)
T size(T... args)
typedef uint64_t
strcmp
Helper to specify parameter ranges.
Definition parameter.hh:20
Value type used to interface with various property types.
Definition value.hh:53
T substr(T... args)
typedef ssize_t