Sygaldry
Loading...
Searching...
No Matches
set.hpp
1#pragma once
2/*
3Copyright 2023 Travis J. West, https://traviswest.ca, Input Devices and Music Interaction Laboratory
4(IDMIL), Centre for Interdisciplinary Research in Music Media and Technology
5(CIRMMT), McGill University, Montréal, Canada, and Univ. Lille, Inria, CNRS,
6Centrale Lille, UMR 9189 CRIStAL, F-59000 Lille, France
7
8SPDX-License-Identifier: MIT
9*/
10
11#include <charconv>
12#include "sygac-endpoints.hpp"
13#include "sygbp-osc_string_constants.hpp"
14#include "sygbp-osc_match_pattern.hpp"
15
16namespace sygaldry { namespace sygbp {
19
20struct Set
21{
22 static _consteval auto name() { return "/set"; }
23 static _consteval auto usage() { return "component-name endpoint-name [value] [value] [...]"; }
24 static _consteval auto description() { return "Change the current value of the given endoint"; }
25
26 template<typename T>
27 requires std::integral<T>
28 T from_chars(const char * start, const char * end, bool& success)
29 {
30 T ret{};
31 auto [ptr, ec] = std::from_chars(start, end, ret);
32 if (ec == std::errc{}) success = true;
33 else success = false;
34 return ret;
35 }
36
37 template<typename T>
38 requires std::floating_point<T>
39 T from_chars(const char * start, const char * end, bool& success)
40 {
41 #ifdef ESP_PLATFORM
42 char * e;
43 T ret;
44 if constexpr (std::is_same_v<T, float>)
45 ret = std::strtof(start, &e);
46 else if constexpr (std::is_same_v<T, double>)
47 ret = std::strtod(start, &e);
48 else if constexpr (std::is_same_v<T, long double>)
49 ret = std::strtold(start, &e);
50 if (start == e) success = false;
51 else success = true;
52 return ret;
53 #else
54 T ret;
55 auto [ptr, ec] = std::from_chars(start, end, ret);
56 if (ec == std::errc{}) success = true;
57 else success = false;
58 return ret;
59 #endif
60 }
61 template<typename T>
62 requires requires (T t, const char * s) {t = s;}
63 T from_chars(const char * start, const char *, bool& success)
64 {
65 success = true;
66 return start;
67 }
68
69 template<typename T>
70 int parse_and_set(auto& log, auto& endpoint, const char * argstart)
71 {
72 auto argend = argstart;
73
74 // search for the end of the token, with an arbitrary maximum upper bound
75 for (int i = 0; *argend != 0 && i < 256; ++i, ++argend) {}
76 if (*argend != 0)
77 {
78 log.println("Unable to parse number, couldn't find end of token");
79 return 2;
80 }
81 bool success = false;
82 T val = from_chars<T>(argstart, argend, success);
83 if (success)//ec == std::errc{})
84 {
85 endpoint = val;
86 return 0;
87 }
88 else
89 {
90 log.println("Unable to parse token '", argstart, "'");
91 return 2;
92 }
93 }
94 int parse_and_set(auto& log, auto& endpoint, int argc, char ** argv)
95 {
96 for (int i = 0; i < argc; ++i)
97 {
98 using T = decltype(value_of(endpoint)[0]);
99 auto ret = parse_and_set<std::remove_cvref_t<T>>(log, value_of(endpoint)[i], argv[i]);
100 if (ret != 0) return ret;
101 }
102 return 0;
103 }
104
105 template<typename T>
106 int set_endpoint_value(auto& log, T& endpoint, int argc, char ** argv)
107 {
108 if constexpr (Bang<T>)
109 {
110 if (argc != 0) log.println("Note: no arguments are required to set a bang.");
111 set_value(endpoint, true);
112 return 0;
113 }
114 else if constexpr (array_like<value_t<T>>)
115 {
116 if (argc < size<value_t<T>>())
117 {
118 log.println("Not enough arguments to set this endpoint.");
119 return 2;
120 }
121 else return parse_and_set(log, endpoint, argc, argv);
122 }
123 else if constexpr (has_value<T>)
124 {
125 if (argc < 1)
126 {
127 log.println("Not enough arguments to set this endpoint.");
128 return 2;
129 }
130 else return parse_and_set<value_t<T>>(log, endpoint, argv[0]);
131 }
132 else return 2;
133 }
134
135 template<typename Components>
136 int main(int argc, char** argv, auto& log, Components& components)
137 {
138 if (argc < 2)
139 {
140 log.println("usage: ", usage());
141 return 2;
142 }
143 for_each_endpoint(components, [&]<typename T>(T& endpoint) {
144 if (osc_match_pattern(argv[1], osc_path_v<T, Components>))
145 set_endpoint_value(log, endpoint, argc-2, argv+2);
146 });
147 return 0;
148 }
149
150};
151
153} }
Definition sygac-endpoints.hpp:92
Definition sygac-endpoints.hpp:166
Definition sygac-endpoints.hpp:121
bool osc_match_pattern(const char *pattern, const char *address)
Match an OSC address pattern against the given address.
Definition sygbp-osc_match_pattern.cpp:12
Definition set.hpp:21