22 halp_meta(name,
"Switch")
23 halp_meta(c_name,
"avnd_switch")
24 halp_meta(category,
"Control/Mappings")
25 halp_meta(author,
"ossia score")
28 "Route each event to the first matching case: a number, true, false, null "
29 "(matches impulse), or a string, quoted or not. Strings and booleans match "
30 "without coercion; numbers compare exactly after promotion to double. "
31 "Invalid literals never match. Row identities keep cables through reordering.")
32 halp_meta(uuid,
"51083c8f-aea0-4617-b026-34fd2793c818")
38 halp_meta(name,
"Input")
39 ossia::value_port* value{};
40 static constexpr bool is_event() {
return true; }
42 struct : halp::string_list<
"Cases">
46 "Numbers, true, false, null, or strings (quotes optional). "
47 "The first matching row receives the event; null matches impulse.")
48 void update(
Switch& self) { self.compile(); }
49 static std::function<void(
Switch&,
const halp::string_list_value&)>
50 on_controller_interaction()
52 return [](
Switch& self,
const halp::string_list_value& rows) {
53 self.outputs.cases.set_rows(rows);
61 halp_meta(name,
"Case {}")
62 ossia::value_port* value{};
63 static constexpr bool is_event() {
return true; }
69 halp_meta(name,
"Unmatched")
70 ossia::value_port* value{};
71 static constexpr bool is_event() {
return true; }
73 halp::keyed_dynamic_port<case_port> cases;
90 bool matches(
const ossia::value& value)
const
95 return value.target<ossia::impulse>();
97 if(
auto v = value.target<
bool>())
101 if(
auto v = value.target<
int>())
102 return double(*v) == numeric;
103 if(
auto v = value.target<
float>())
104 return double(*v) == numeric;
107 if(
auto v = value.target<std::string>())
115 std::vector<Literal> literals;
117 using tick = ossia::token_request;
118 ossia::exec_state_facade ossia_state;
123 literals.reserve(inputs.cases.value.size());
124 for(
const auto& [
id, text] : inputs.cases.value)
126 auto& literal = literals.emplace_back();
127 rapidjson::Document json;
128 if(text.find(
'\0') != std::string::npos)
130 json.Parse<rapidjson::kParseValidateEncodingFlag>(text.data(), text.size());
131 if(json.HasParseError())
135 std::string_view word{text};
136 while(!word.empty() && std::isspace(
static_cast<unsigned char>(word.front())))
137 word.remove_prefix(1);
138 while(!word.empty() && std::isspace(
static_cast<unsigned char>(word.back())))
139 word.remove_suffix(1);
142 literal.kind = Literal::string;
143 literal.text.assign(word);
148 literal.kind = Literal::null;
149 else if(json.IsBool())
151 literal.kind = Literal::boolean;
152 literal.flag = json.GetBool();
154 else if(json.IsNumber())
156 literal.kind = Literal::number;
157 literal.numeric = json.GetDouble();
159 else if(json.IsString())
161 literal.kind = Literal::string;
162 literal.text.assign(json.GetString(), json.GetStringLength());
167 void operator()(
const tick& t)
169 if(!inputs.input.value)
171 const auto [start, frames] = ossia_state.timings(t);
172 for(
const auto& event : inputs.input.value->get_data())
174 if(event.timestamp < start || event.timestamp >= start + frames)
176 auto output = outputs.unmatched.value;
177 for(std::size_t i = 0; i < literals.size() && i < outputs.cases.ports.size(); ++i)
178 if(literals[i].
matches(event.value))
180 output = outputs.cases.ports[i].value;
184 output->write_value(event.value, event.timestamp);