Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed expanding runtime variables #241

Merged
merged 2 commits into from
Sep 24, 2020
Merged

Fixed expanding runtime variables #241

merged 2 commits into from
Sep 24, 2020

Conversation

PunishedSnakePr
Copy link
Contributor

For a detailed description please see commit message of first commit (826faf7).

Expanding variables at runtime (that have not
been registered before), for example in
"ucl_parser_set_variables_handler" function,
always expanded to an empty string though
"replace" and "replace_len" were set properly.

Example config:
{
    foo = Hello World!;
    bar = ${foo};
}

Shortened unknown variable handler code:
[...]

root = ucl_parser_get_object(parser);
var = ucl_object_lookup_path(root, path);
*replace = (unsigned char*)var->value.sv;
*replace_len = var->len;
*need_free = false;
return true;

[...]

In the above handler code "path" is "foo" but could
be any dot notation path to an already existing
object.

UCL emitter always output:
{
    foo = "Hello World!";
    bar = "";
}

Forwarding announced replaced data len from handler to
"ucl_check_variable_safe" fixed the issue.
@vstakhov
Copy link
Owner

Hum, do we have a test case for that? How have you reveled this issue?

@PunishedSnakePr
Copy link
Contributor Author

PunishedSnakePr commented Sep 23, 2020

I need to dig into the way you organize your test cases but sure I'll provide one.

In general, I was lacking a way to register variables at runtime (not at compile time) so users can declare their own variables and use them later on in the config. Therefore I used the "ucl_parser_set_variables_handler" to catch all dynamic/unknown variables, looked them up in a special "variable" config object and tried to replace the variable with its related content. Everything seemed to work as expected but in the end the variable was always empty.

Example config:

{
     vars {
        foo = hello
    }

    bar = ${vars.foo}
}

This is my original callback handler for the config example above:

static bool
__ucl_var_handler(const unsigned char *data,
                              size_t data_len,
                              unsigned char **replace,
                              size_t *replace_len,
                              bool *need_free,
                              void *priv_data)
{
    bool rv;
    char *path;
    struct ucl_parser *parser;
    ucl_object_t *root;
    const ucl_object_t *var;

    *need_free = false;

    path = strndup((const char*)data, data_len);
    if (!path)
        return false;

    parser = priv_data;
    rv = false;

    root = ucl_parser_get_object(parser);
    if (!root)
        goto err_path;

    var = ucl_object_lookup_path(root, path);
    if (!var)
        goto err_unref;

    *replace = (unsigned char*)var->value.sv;
    *replace_len = var->len;

    rv = true;

err_unref:
    ucl_object_unref(root);

err_path:
    free(path);

    return rv;
}

And this is the result when emitting "root" object:

{
     vars {
        foo = "hello";
    }

    bar = "";
}

My commit fixes this issue (as I'd expect it to work in general) and creates this output:

{
     vars {
        foo = "hello";
    }

    bar = "hello";
}

@PunishedSnakePr
Copy link
Contributor Author

PunishedSnakePr commented Sep 24, 2020

From my perspective this would be a cool feature anyway which helps reducing redundant config lines and increasing usability / flexibility. If you are fine with it, I am very happy to implement it as a native UCL feature.

@vstakhov
Copy link
Owner

I agree, you are right, thank you!

@vstakhov vstakhov merged commit 10c4dad into vstakhov:master Sep 24, 2020
@PunishedSnakePr PunishedSnakePr deleted the fixed-expanding-runtime-variables branch September 24, 2020 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants