19 halp_meta(name,
"Switch")
20 halp_meta(c_name,
"avnd_switch")
21 halp_meta(category,
"Control/Mappings")
22 halp_meta(author,
"ossia score")
25 "Route each event to the first matching JSON scalar case. Strings and booleans "
26 "match without coercion; numbers compare exactly after promotion to double; null "
28 "Invalid literals never match. Row identities keep cables through reordering.")
29 halp_meta(uuid,
"51083c8f-aea0-4617-b026-34fd2793c818")
35 halp_meta(name,
"Input")
36 ossia::value_port* value{};
37 static constexpr bool is_event() {
return true; }
39 struct : halp::string_list<
"Cases">
43 "JSON scalars: quoted strings, numbers, true, false or null. "
44 "The first matching row receives the event; null matches impulse.")
45 void update(
Switch& self) { self.compile(); }
46 static std::function<void(
Switch&,
const halp::string_list_value&)>
47 on_controller_interaction()
49 return [](
Switch& self,
const halp::string_list_value& rows) {
50 self.outputs.cases.set_rows(rows);
58 halp_meta(name,
"Case {}")
59 ossia::value_port* value{};
60 static constexpr bool is_event() {
return true; }
66 halp_meta(name,
"Unmatched")
67 ossia::value_port* value{};
68 static constexpr bool is_event() {
return true; }
70 halp::keyed_dynamic_port<case_port> cases;
87 bool matches(
const ossia::value& value)
const
92 return value.target<ossia::impulse>();
94 if(
auto v = value.target<
bool>())
98 if(
auto v = value.target<
int>())
99 return double(*v) == numeric;
100 if(
auto v = value.target<
float>())
101 return double(*v) == numeric;
104 if(
auto v = value.target<std::string>())
112 std::vector<Literal> literals;
114 using tick = ossia::token_request;
115 ossia::exec_state_facade ossia_state;
120 literals.reserve(inputs.cases.value.size());
121 for(
const auto& [
id, text] : inputs.cases.value)
123 auto& literal = literals.emplace_back();
124 rapidjson::Document json;
125 if(text.find(
'\0') != std::string::npos)
127 json.Parse<rapidjson::kParseValidateEncodingFlag>(text.data(), text.size());
128 if(json.HasParseError())
131 literal.kind = Literal::null;
132 else if(json.IsBool())
134 literal.kind = Literal::boolean;
135 literal.flag = json.GetBool();
137 else if(json.IsNumber())
139 literal.kind = Literal::number;
140 literal.numeric = json.GetDouble();
142 else if(json.IsString())
144 literal.kind = Literal::string;
145 literal.text.assign(json.GetString(), json.GetStringLength());
150 void operator()(
const tick& t)
152 if(!inputs.input.value)
154 const auto [start, frames] = ossia_state.timings(t);
155 for(
const auto& event : inputs.input.value->get_data())
157 if(event.timestamp < start || event.timestamp >= start + frames)
159 auto output = outputs.unmatched.value;
160 for(std::size_t i = 0; i < literals.size() && i < outputs.cases.ports.size(); ++i)
161 if(literals[i].
matches(event.value))
163 output = outputs.cases.ports[i].value;
167 output->write_value(event.value, event.timestamp);