Skip to content

Latest commit

 

History

History
163 lines (149 loc) · 5.46 KB

README.md

File metadata and controls

163 lines (149 loc) · 5.46 KB

How to install

Just drop the corresponding files inside of your project and you are golden!

As alternative, you may also add this as submodule and setup your environment like a pro.

Components

Methodhost

For using methodhost, you need to add #include "methodhost.hpp" to the top of your C++ file and add the following method to it:

sqf::methodhost& sqf::methodhost::instance()
{
    using namespace std::string_literals;
    static sqf::methodhost h({
        });
    return h;
}

Adding methods then can be done, by simply adding it to the initializer list:

sqf::methodhost h({
    { "my_fancy_method", { sqf::method::create(
        [](
            // required SCALAR value at index 0
            float req_scalar,
            // required STRING value at index 1
            std::string string,
            // required BOOLEAN value at index 2
            bool boolean,
            // optional ARRAY value at index 3
            std::optional<std::vector<sqf::value>> opt_array)
        // note that sqf::methodhost::ret<Tok, Terr> is for returning either
        // a good result or an error result. You also may return any other supported type
        // instead
        -> sqf::methodhost::ret<float, std::string> {
            ...
            // To return a value, you can either do one of the following:
            return { 1.0, {} }; // ok
            return { {}, "something broke" }; // error
            return 1.0; // ok - requires that the error and ok types are different
            return "something broke"; // err - requires that the error and ok types are different
            return sqf::methodhost::ret<float, std::string>::ok(1.0); // ok
            return sqf::methodhost::ret<float, std::string>::err("something broke"); // error
        }
    ), ... } },
};

and the methodhost will mangle the functions properly. Note that std::optional<...> can be used for optional parameters and that overloading works only on the parameters.

To then use the methodhost, you use the following code:

__declspec (dllexport) int __stdcall RVExtensionArgs(char* output, int outputSize, const char* function, const char** argv, int argc)
{
    auto res = sqf::methodhost::instance().execute(output, outputSize, function, argv, argc);
    return res;
}

on the SQF side, scripts can call the extension using:

params ["_method", "_args"];
private _result = "";
private _longResult = nil;
// do a call for an extra variable scope
0 call {
    ("extFileIO" callExtension [_method, _args]) params ["_resultData", "_returnCode", "_errorCode"];
    if (_errorCode != 0) then { throw _errorCode; };
    switch _returnCode do {
        case -1: { _result = (parseSimpleArray format["[%1]", _resultData]) select 0; throw _result; };
        case 0: { _result = (parseSimpleArray format["[%1]", _resultData]) select 0; };
        case 1: { _longResult = (parseSimpleArray format["[%1]", _resultData]) select 0; };
    };
};
// while in long result, keep polling
while { !isNil "_longResult" } do
{
    ("extFileIO" callExtension ["?", _longResult]) params ["_resultData", "_returnCode", "_errorCode"];
    if (_errorCode != 0) then { throw _errorCode; };
    switch _returnCode do {
        case -1: { _result = (parseSimpleArray format["[%1]", _result + _resultData]) select 0; throw _result; };
        case 0: { _result = (parseSimpleArray format["[%1]", _result + _resultData]) select 0; _longResult = nil; };
        case 1: { _result = _result + _resultData; };
    };
};
_result

SQF-Value

Using sqf-value is rather straight forward. You just add the #include "value.hpp" to the top of your C++ file and can start going!

// Creating a string
sqf::value s = "Happyface: \":)\"";
// Gives you
std::cout << s.to_string() << std::endl; /* `"Happyface: "":)"""` */

// Parsing an array?
auto arr = sqf::value::parse("[1, 2, 3, 4, 5]");
// No problem!
std::cout << float(arr[4]) << std::endl; /* `5` */

// Have numerical stuff to solve?
sqf::value val = 12.5;
// just do it!
std::cout << (val + 7.5) << std::endl; /* `20` */

as you can see, sqf-value got it all and is really simple to use and provides you with the magic horsepower you need to run your extensions as you never did before :)

Ohh and ... by the way ... it also supports nested equality checks:

sqf::value val({ 1,2,{ 1,2,3,4,5 },4,5 });
sqf::value other = sqf::value::parse("[1,2,[1,2,3,4,5],4,5]");

std::cout << (val == other) << std::endl; /* `true` */

so no need to worry about that either 😛

And in the case that you would like to parse raw strings, you can do the following:

using namespace sqf;
sqf::value val = "['this is my fancy array', 1, true, nil]"_sqf;

If you want to check if something is a certain type, you can do one of the following:

sqf::value val = ...;
// check if value is SCALAR
sqf::is<float>(val);
val.is_scalar();
// check if value is STRING
sqf::is<std::string>(val);
val.is_string();
// check if value is BOOLEAN
sqf::is<bool>(val);
val.is_boolean();
// check if value is ARRAY
sqf::is<std::vector<sqf::value>>(val);
val.is_array();
// check if value is NIL
sqf::is<void>(val);
val.is_nil();

and for getting a certain type, the following methods are available:

sqf::value val = ...;
// get value as SCALAR
sqf::get<float>(val);
val.as_scalar();
// get value as STRING
sqf::get<std::string>(val);
val.as_string();
// get value as BOOLEAN
sqf::get<bool>(val);
val.as_boolean();
// get value as ARRAY
sqf::get<std::vector<sqf::value>>(val);
val.as_array();