/**
* Returns the name of the given function
*
* Params:
* func = the function alias to get the name of
*
* Returns: the name of the function
*/
template functionNameOf (alias func)
{
version(LDC)
const functionNameOf = (&func).stringof[1 .. $];
else
const functionNameOf = (&func).stringof[2 .. $];
}
/**
* Returns the parameter names of the given function
*
* Params:
* func = the function alias to get the parameter names of
*
* Returns: an array of strings containing the parameter names
*/
template parameterNamesOf (alias func)
{
const parameterNamesOf = parameterNamesOfImpl!(func);
}
/**
* Returns the parameter names of the given function
*
* Params:
* func = the function alias to get the parameter names of
*
* Returns: an array of strings containing the parameter names
*/
private string[] parameterNamesOfImpl (alias func) ()
{
string funcStr = typeof(&func).stringof;
auto start = funcStr.indexOf('(');
auto end = funcStr.indexOf(')');
const firstPattern = ' ';
const secondPattern = ',';
funcStr = funcStr[start + 1 .. end];
if (funcStr == "")
return null;
funcStr ~= secondPattern;
string token;
string[] arr;
foreach (c ; funcStr)
{
if (c != firstPattern && c != secondPattern)
token ~= c;
else
{
if (token)
arr ~= token;
token = null;
}
}
if (arr.length == 1)
return arr;
string[] result;
bool skip = false;
foreach (str ; arr)
{
skip = !skip;
if (skip)
continue;
result ~= str;
}
return result;
}
/**
* Helper function for callWithNamedArguments
*
* Returns:
*/
private string buildFunction (alias func, string args) ()
{
const str = split(args);
string[] params;
string[] values;
auto mixinString = functionNameOf!(func) ~ "(";
foreach (s ; str)
{
auto index = s.indexOf('=');
params ~= s[0 .. index];
values ~= s[index + 1 .. $];
}
const parameterNames = parameterNamesOf!(func);
foreach (i, s ; parameterNames)
{
auto index = params.indexOf(s);
if (index != params.length)
mixinString ~= values[index] ~ ",";
}
return mixinString[0 .. $ - 1] ~ ");";
}
/**
* Calls the given function with named arguments
*
* Params:
* func = an alias to the function to call
* args = a string containing the arguments to call using this syntax: `arg2=value,arg1="value"`
*/
void callWithNamedArguments (alias func, string args) ()
{
mixin(buildFunction!(func, args));
}