Skip to content

Commit d70db8b

Browse files
committed
improve function wrapper
1 parent bf9a864 commit d70db8b

File tree

4 files changed

+82
-124
lines changed

4 files changed

+82
-124
lines changed

include/rift/config.hpp

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,17 @@ namespace rift {
2525
|| std::same_as<T, Object>;
2626

2727
using RuntimeFuncResult = geode::Result<Value>;
28-
using RuntimeFunction = std::function<RuntimeFuncResult(std::span<Value const>)>;
28+
using RuntimeFunction = std::function<RuntimeFuncResult(std::span<Value>)>;
2929
using RuntimeFunctions = std::unordered_map<std::string, RuntimeFunction>;
3030

3131
/// @brief Global configuration for the Rift library.
3232
class Config {
3333
Config();
34+
public:
3435
Config(Config const&) = delete;
3536
Config(Config&&) = delete;
3637
Config& operator=(Config const&) = delete;
3738

38-
public:
3939
/// @brief Returns the global configuration instance.
4040
static Config& get() noexcept;
4141

@@ -77,37 +77,27 @@ namespace rift {
7777
}
7878

7979
private:
80-
template <size_t I, typename T, typename... Args>
81-
static geode::Result<std::tuple<T, Args...>> unwrapArgsImpl(std::span<Value const> args) {
82-
if constexpr (sizeof...(Args) > 0) {
83-
auto rest = unwrapArgsImpl<I + 1, Args...>(args);
84-
if (rest.isErr()) {
85-
return geode::Err(rest.unwrapErr());
86-
}
87-
auto canUnwrap = args[I].is<T>();
88-
if (!canUnwrap) {
89-
return geode::Err("Argument type mismatch");
90-
}
91-
return geode::Ok(std::tuple_cat(std::tuple<T>{args[I].to<T>()}, std::move(rest.unwrap())));
92-
} else {
93-
return geode::Ok(std::tuple<T>(args[I].to<T>()));
94-
}
95-
}
96-
97-
template <std::size_t I>
98-
static geode::Result<std::tuple<>> unwrapArgsImpl(std::span<const Value>) {
99-
return geode::Ok(std::tuple());
100-
}
101-
10280
template <typename... Args>
103-
static geode::Result<std::tuple<Args...>> unwrapArgs(std::span<Value const> args) {
104-
if constexpr (sizeof...(Args) != 0) {
105-
if (args.size() != sizeof...(Args)) {
81+
static geode::Result<std::tuple<std::remove_cvref_t<Args>...>> unwrapArgs(std::span<Value> args) {
82+
if constexpr (sizeof...(Args) == 0) {
83+
return geode::Ok(std::tuple<>());
84+
} else {
85+
if (args.size() < sizeof...(Args)) {
10686
return geode::Err("Argument count mismatch");
10787
}
108-
return unwrapArgsImpl<0, Args...>(args);
109-
} else {
110-
return geode::Ok(std::tuple<Args...>());
88+
89+
return [&]<size_t... I>(std::index_sequence<I...>) -> geode::Result<std::tuple<std::remove_cvref_t<Args>...>> {
90+
std::tuple<std::remove_cvref_t<Args>...> argsTuple;
91+
bool success = true;
92+
((success && args[I].template is<std::remove_cvref_t<Args>>()
93+
? void(std::get<I>(argsTuple) = args[I].template to<std::remove_cvref_t<Args>>())
94+
: void(success = false)), ...);
95+
96+
if (!success) {
97+
return geode::Err("Argument type mismatch");
98+
}
99+
return geode::Ok(std::move(argsTuple));
100+
}(std::make_index_sequence<sizeof...(Args)>());
111101
}
112102
}
113103

@@ -120,7 +110,7 @@ namespace rift {
120110
/// @param func the function pointer
121111
template <typename Ret, typename... Args>
122112
void makeFunction(std::string const& name, Ret(*func)(Args...)) noexcept {
123-
m_functions[name] = [func](std::span<Value const> args) -> RuntimeFuncResult {
113+
m_functions[name] = [func](std::span<Value> args) -> RuntimeFuncResult {
124114
// Unwrap the arguments with deduced types
125115
auto res = unwrapArgs<Args...>(args);
126116
if (res.isErr()) {
@@ -132,7 +122,7 @@ namespace rift {
132122
std::apply(func, res.unwrap());
133123
return geode::Ok(Value());
134124
} else {
135-
Ret ret = std::apply(func, res.unwrap());
125+
Ret ret = std::apply(func, std::move(res.unwrap()));
136126

137127
// Convert the result to the correct type
138128
if constexpr (std::same_as<Ret, RuntimeFuncResult>) {

include/rift/value.hpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -179,13 +179,12 @@ namespace rift {
179179
template <typename T>
180180
bool is() const noexcept {
181181
using type = std::remove_cvref_t<T>;
182-
if constexpr (std::is_same_v<type, std::string>) {
183-
return true;
184-
} else if constexpr (std::is_same_v<type, int64_t>) {
185-
return true;
186-
} else if constexpr (std::is_same_v<type, double>) {
187-
return true;
188-
} else if constexpr (std::is_same_v<type, bool>) {
182+
if constexpr (
183+
std::is_same_v<type, std::string> ||
184+
std::is_same_v<type, int64_t> ||
185+
std::is_same_v<type, double> ||
186+
std::is_same_v<type, bool>
187+
) {
189188
return true;
190189
} else if constexpr (std::is_same_v<type, Array>) {
191190
return isArray();

src/config.cpp

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ namespace rift {
1010
// Cast functions
1111
int64_t intCast(int64_t value) noexcept { return value; }
1212
double floatCast(double value) noexcept { return value; }
13-
std::string strCast(std::string value) noexcept { return value; }
13+
std::string strCast(std::string&& value) noexcept { return value; }
1414

1515
// String functions
16-
RuntimeFuncResult length(std::span<const Value> args) noexcept {
16+
RuntimeFuncResult length(std::span<Value> args) noexcept {
1717
if (args.size() != 1) {
1818
return geode::Err("Expected 1 argument");
1919
}
@@ -35,21 +35,21 @@ namespace rift {
3535
return geode::Ok(static_cast<int64_t>(arg.toString().size()));
3636
}
3737

38-
std::string toUpper(std::string str) noexcept {
39-
for (auto& c : str) {
40-
c = std::toupper(c);
41-
}
38+
std::string toUpper(std::string&& str) noexcept {
39+
std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) {
40+
return std::toupper(c);
41+
});
4242
return str;
4343
}
4444

45-
std::string toLower(std::string str) noexcept {
46-
for (auto& c : str) {
47-
c = std::tolower(c);
48-
}
45+
std::string toLower(std::string&& str) noexcept {
46+
std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) {
47+
return std::tolower(c);
48+
});
4949
return str;
5050
}
5151

52-
std::string substrImpl(const std::string &str, int64_t start, int64_t count) noexcept {
52+
std::string substrImpl(std::string const& str, int64_t start, int64_t count) noexcept {
5353
// If string is empty, return empty string
5454
if (str.empty()) {
5555
return "";
@@ -81,7 +81,7 @@ namespace rift {
8181
return str.substr(start, count);
8282
}
8383

84-
RuntimeFuncResult substr(std::span<Value const> args) noexcept {
84+
RuntimeFuncResult substr(std::span<Value> args) noexcept {
8585
if (args.size() != 3 && args.size() != 2) {
8686
return geode::Err("Expected 2 or 3 arguments");
8787
}
@@ -95,7 +95,7 @@ namespace rift {
9595
));
9696
}
9797

98-
std::string trim(std::string str) noexcept {
98+
std::string trim(std::string&& str) noexcept {
9999
// Find the first non-whitespace character
100100
auto start = str.find_first_not_of(" \t\n\r\f\v");
101101
if (start == std::string::npos) {
@@ -109,7 +109,7 @@ namespace rift {
109109
return str.substr(start, end - start + 1);
110110
}
111111

112-
std::string replace(std::string str, std::string from, std::string to) noexcept {
112+
std::string replace(std::string&& str, std::string&& from, std::string&& to) noexcept {
113113
size_t start = 0;
114114
while ((start = str.find(from, start)) != std::string::npos) {
115115
str.replace(start, from.length(), to);
@@ -118,7 +118,7 @@ namespace rift {
118118
return str;
119119
}
120120

121-
int64_t find(std::string str, std::string substr) noexcept {
121+
int64_t find(std::string&& str, std::string&& substr) noexcept {
122122
return str.find(substr);
123123
}
124124

@@ -165,7 +165,7 @@ namespace rift {
165165
return fmt::format("{}.{:03}", seconds, millis);
166166
}
167167

168-
RuntimeFuncResult middlePad(std::span<Value const> args) noexcept {
168+
RuntimeFuncResult middlePad(std::span<Value> args) noexcept {
169169
if (args.size() != 2 && args.size() != 3) {
170170
return geode::Err("Expected 2 or 3 arguments");
171171
}
@@ -187,7 +187,7 @@ namespace rift {
187187
return geode::Ok(std::string(leftPad, pad[0]) + str + std::string(rightPad, pad[0]));
188188
}
189189

190-
RuntimeFuncResult leftPad(std::span<Value const> args) noexcept {
190+
RuntimeFuncResult leftPad(std::span<Value> args) noexcept {
191191
if (args.size() != 2 && args.size() != 3) {
192192
return geode::Err("Expected 2 or 3 arguments");
193193
}
@@ -207,7 +207,7 @@ namespace rift {
207207
return geode::Ok(std::string(padSize, pad[0]) + str);
208208
}
209209

210-
RuntimeFuncResult rightPad(std::span<Value const> args) noexcept {
210+
RuntimeFuncResult rightPad(std::span<Value> args) noexcept {
211211
if (args.size() != 2 && args.size() != 3) {
212212
return geode::Err("Expected 2 or 3 arguments");
213213
}
@@ -227,7 +227,7 @@ namespace rift {
227227
return geode::Ok(str + std::string(padSize, pad[0]));
228228
}
229229

230-
RuntimeFuncResult min(std::span<Value const> args) noexcept {
230+
RuntimeFuncResult min(std::span<Value> args) noexcept {
231231
if (args.empty()) {
232232
return geode::Err("Expected at least one argument");
233233
}
@@ -242,7 +242,7 @@ namespace rift {
242242
return geode::Ok(std::move(min));
243243
}
244244

245-
RuntimeFuncResult max(std::span<Value const> args) noexcept {
245+
RuntimeFuncResult max(std::span<Value> args) noexcept {
246246
if (args.empty()) {
247247
return geode::Err("Expected at least one argument");
248248
}
@@ -257,20 +257,20 @@ namespace rift {
257257
return geode::Ok(std::move(max));
258258
}
259259

260-
RuntimeFuncResult sum(std::span<Value const> args) noexcept {
260+
RuntimeFuncResult sum(std::span<Value> args) noexcept {
261261
if (args.empty()) {
262262
return geode::Err("Expected at least one argument");
263263
}
264264

265265
double sum = 0;
266-
for (size_t i = 0; i < args.size(); ++i) {
267-
sum += args[i].toFloat();
266+
for (auto const& arg : args) {
267+
sum += arg.toFloat();
268268
}
269269

270270
return geode::Ok(sum);
271271
}
272272

273-
RuntimeFuncResult avg(std::span<Value const> args) noexcept {
273+
RuntimeFuncResult avg(std::span<Value> args) noexcept {
274274
if (args.empty()) {
275275
return geode::Err("Expected at least one argument");
276276
}
@@ -297,7 +297,7 @@ namespace rift {
297297
return dist(gen);
298298
}
299299

300-
RuntimeFuncResult random(std::span<Value const> args) noexcept {
300+
RuntimeFuncResult random(std::span<Value> args) noexcept {
301301
if (args.size() != 2) {
302302
return geode::Err("Expected 2 arguments");
303303
}
@@ -309,11 +309,11 @@ namespace rift {
309309
return geode::Ok(randomInt(args[0].toInteger(), args[1].toInteger()));
310310
}
311311

312-
RuntimeFuncResult createArray(std::span<Value const> args) noexcept {
312+
RuntimeFuncResult createArray(std::span<Value> args) noexcept {
313313
return geode::Ok(Array(args.begin(), args.end()));
314314
}
315315

316-
RuntimeFuncResult createArrayN(std::span<Value const> args) noexcept {
316+
RuntimeFuncResult createArrayN(std::span<Value> args) noexcept {
317317
if (args.size() != 2) {
318318
return geode::Err("Expected 2 arguments");
319319
}
@@ -322,7 +322,7 @@ namespace rift {
322322
return geode::Ok(Array(count, args[1]));
323323
}
324324

325-
RuntimeFuncResult setElement(std::span<Value const> args) noexcept {
325+
RuntimeFuncResult setElement(std::span<Value> args) noexcept {
326326
if (args.size() != 3) {
327327
return geode::Err("Expected 3 arguments");
328328
}
@@ -366,7 +366,7 @@ namespace rift {
366366
return geode::Err("First argument must be an array, object, or string");
367367
}
368368

369-
std::string joinArray(Array arr, std::string separator) noexcept {
369+
std::string joinArray(Array&& arr, std::string&& separator) noexcept {
370370
std::string result;
371371
for (size_t i = 0; i < arr.size(); ++i) {
372372
if (i > 0) {

0 commit comments

Comments
 (0)