示例#1
0
static void test_extract_scalar_prefix()
{
    Buffer *b = BufferNew();
    assert_int_equal(sizeof("hello ") - 1, ExtractScalarPrefix(b, "hello $(world) xy", sizeof("hello $(world) xy") -1));
    assert_string_equal("hello ", BufferData(b));

    BufferClear(b);
    assert_int_equal(sizeof("hello (world) xy") -1, ExtractScalarPrefix(b, "hello (world) xy", sizeof("hello (world) xy") -1));
    assert_string_equal("hello (world) xy", BufferData(b));

    BufferClear(b);
    assert_int_equal(sizeof("hello$)") -1, ExtractScalarPrefix(b, "hello$)$(world)xy", sizeof("hello$)$(world)xy") -1));
    assert_string_equal("hello$)", BufferData(b));

    BufferClear(b);
    assert_int_equal(0, ExtractScalarPrefix(b, "", 0));
    assert_string_equal("", BufferData(b));

    BufferDestroy(b);
}
示例#2
0
文件: expand.c 项目: tzz/core
bool ExpandScalar(const EvalContext *ctx, const char *ns, const char *scope, const char *string, Buffer *out)
{
    assert(string);

    bool returnval = true;

    if (strlen(string) == 0)
    {
        return false;
    }

    // TODO: cleanup, optimize this mess
    Buffer *var = BufferNew();
    Buffer *current_item = BufferNew();
    Buffer *temp = BufferNew();
    for (const char *sp = string; /* No exit */ ; sp++)     /* check for varitems */
    {
        char varstring = false;
        size_t increment = 0;

        if (*sp == '\0')
        {
            break;
        }

        BufferZero(current_item);
        ExtractScalarPrefix(current_item, sp, strlen(sp));

        BufferAppend(out, BufferData(current_item), BufferSize(current_item));
        sp += BufferSize(current_item);

        if (*sp == '\0')
        {
            break;
        }

        BufferZero(var);
        if (*sp == '$')
        {
            switch (*(sp + 1))
            {
            case '(':
                varstring = ')';
                ExtractScalarReference(var, sp, strlen(sp), false);
                if (BufferSize(var) == 0)
                {
                    BufferAppendChar(out, '$');
                    continue;
                }
                break;

            case '{':
                varstring = '}';
                ExtractScalarReference(var, sp, strlen(sp), false);
                if (BufferSize(var) == 0)
                {
                    BufferAppendChar(out, '$');
                    continue;
                }
                break;

            default:
                BufferAppendChar(out, '$');
                continue;
            }
        }

        BufferZero(current_item);
        {
            BufferZero(temp);
            ExtractScalarReference(temp, sp, strlen(sp), true);

            if (IsCf3VarString(BufferData(temp)))
            {
                ExpandScalar(ctx, ns, scope, BufferData(temp), current_item);
            }
            else
            {
                BufferAppend(current_item, BufferData(temp), BufferSize(temp));
            }
        }

        increment = BufferSize(var) - 1;

        char name[CF_MAXVARSIZE] = "";
        if (!IsExpandable(BufferData(current_item)))
        {
            DataType type = DATA_TYPE_NONE;
            const void *value = NULL;
            {
                VarRef *ref = VarRefParseFromNamespaceAndScope(BufferData(current_item), ns, scope, CF_NS, '.');
                value = EvalContextVariableGet(ctx, ref, &type);
                VarRefDestroy(ref);
            }

            if (value)
            {
                switch (type)
                {
                case DATA_TYPE_STRING:
                case DATA_TYPE_INT:
                case DATA_TYPE_REAL:
                    BufferAppend(out, value, strlen(value));
                    break;

                case DATA_TYPE_STRING_LIST:
                case DATA_TYPE_INT_LIST:
                case DATA_TYPE_REAL_LIST:
                case DATA_TYPE_NONE:
                    if (varstring == '}')
                    {
                        snprintf(name, CF_MAXVARSIZE, "${%s}", BufferData(current_item));
                    }
                    else
                    {
                        snprintf(name, CF_MAXVARSIZE, "$(%s)", BufferData(current_item));
                    }

                    BufferAppend(out, name, strlen(name));
                    returnval = false;
                    break;

                default:
                    Log(LOG_LEVEL_DEBUG, "Returning Unknown Scalar ('%s' => '%s')", string, BufferData(out));
                    BufferDestroy(var);
                    BufferDestroy(current_item);
                    BufferDestroy(temp);
                    return false;

                }
            }
            else
            {
                if (varstring == '}')
                {
                    snprintf(name, CF_MAXVARSIZE, "${%s}", BufferData(current_item));
                }
                else
                {
                    snprintf(name, CF_MAXVARSIZE, "$(%s)", BufferData(current_item));
                }

                BufferAppend(out, name, strlen(name));
                returnval = false;
            }
        }

        sp += increment;
        BufferZero(current_item);
    }

    BufferDestroy(var);
    BufferDestroy(current_item);
    BufferDestroy(temp);

    return returnval;
}
示例#3
0
文件: expand.c 项目: tzz/core
static void ExpandAndMapIteratorsFromScalar(EvalContext *ctx, const Bundle *bundle, char *string, size_t length,
                                            int level, Rlist **scalars, Rlist **lists,
                                            Rlist **containers, Rlist **full_expansion)
{
    assert(string);
    if (!string)
    {
        return;
    }

    Buffer *value = BufferNew();

    for (size_t i = 0; i < length; i++)
    {
        const char *sp = string + i;

        Rlist *tmp_list = NULL;
        BufferZero(value);
        if (ExtractScalarPrefix(value, sp, length - i))
        {
            if (full_expansion)
            {
                RlistConcatInto(&tmp_list, *full_expansion, BufferData(value));
                RlistDestroy(*full_expansion);
                *full_expansion = tmp_list;
                tmp_list = NULL;
            }

            sp += BufferSize(value);
            i += BufferSize(value);

            BufferZero(value);

            if (i >= length)
            {
                break;
            }
        }

        if (*sp == '$')
        {
            BufferZero(value);
            ExtractScalarReference(value, sp, length - i, true);
            if (BufferSize(value) > 0)
            {
                Rlist *inner_expansion = NULL;
                Rlist *exp = NULL;
                int success = 0;

                VarRef *ref = VarRefParse(BufferData(value));

                int increment = BufferSize(value) - 1 + 3;

                // Handle any embedded variables
                char *substring = string + i + 2;
                ExpandAndMapIteratorsFromScalar(ctx, bundle, substring, BufferSize(value), level+1, scalars, lists, containers, &inner_expansion);

                for (exp = inner_expansion; exp != NULL; exp = exp->next)
                {
                    // If a list is non-local, i.e. $(bundle.var), map it to local $(bundle#var)

                    // NB without modifying variables as we map them, it's not
                    // possible to handle remote lists referenced by a variable
                    // scope. For example:
                    //  scope => "test."; var => "somelist"; $($(scope)$(var)) fails
                    //  varname => "test.somelist"; $($(varname)) also fails
                    // TODO Unless the consumer handles it?

                    const char *inner_ref_str = RlistScalarValue(exp);
                    VarRef *inner_ref = VarRefParseFromBundle(inner_ref_str, bundle);

                    // var is the expanded name of the variable in its native context
                    // finalname will be the mapped name in the local context "this."

                    DataType value_type = DATA_TYPE_NONE;
                    const void *value = EvalContextVariableGet(ctx, inner_ref, &value_type);
                    if (value)
                    {
                        char *mangled_inner_ref = xstrdup(inner_ref_str);
                        MangleVarRefString(mangled_inner_ref, strlen(mangled_inner_ref));

                        success++;
                        switch (DataTypeToRvalType(value_type))
                        {
                        case RVAL_TYPE_LIST:
                            if (level > 0)
                            {
                                RlistPrependScalarIdemp(lists, mangled_inner_ref);
                            }
                            else
                            {
                                RlistAppendScalarIdemp(lists, mangled_inner_ref);
                            }

                            if (full_expansion)
                            {
                                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                                {
                                    // append each slist item to each of full_expansion
                                    RlistConcatInto(&tmp_list, *full_expansion, RlistScalarValue(rp));
                                }
                            }
                            break;

                        case RVAL_TYPE_SCALAR:
                            RlistAppendScalarIdemp(scalars, mangled_inner_ref);

                            if (full_expansion)
                            {
                                // append the scalar value to each of full_expansion
                                RlistConcatInto(&tmp_list, *full_expansion, value);
                            }
                            break;

                        case RVAL_TYPE_CONTAINER:
                            if (level > 0)
                            {
                                RlistPrependScalarIdemp(containers, mangled_inner_ref);
                            }
                            else
                            {
                                RlistAppendScalarIdemp(containers, mangled_inner_ref);
                            }
                            break;

                        case RVAL_TYPE_FNCALL:
                        case RVAL_TYPE_NOPROMISEE:
                            break;
                        }

                        free(mangled_inner_ref);
                    }

                    VarRefDestroy(inner_ref);
                }
                RlistDestroy(inner_expansion);

                if (full_expansion)
                {
                    RlistDestroy(*full_expansion);
                    *full_expansion = tmp_list;
                    tmp_list = NULL;
                }

                // No need to map this.* even though it's technically qualified
                if (success && IsQualifiedVariable(BufferData(value)) && strcmp(ref->scope, "this") != 0)
                {
                    char *dotpos = strchr(substring, '.');
                    if (dotpos)
                    {
                        *dotpos = CF_MAPPEDLIST;    // replace '.' with '#'
                    }

                    if (strchr(BufferData(value), ':'))
                    {
                        char *colonpos = strchr(substring, ':');
                        if (colonpos)
                        {
                            *colonpos = '*';
                        }
                    }
                }

                VarRefDestroy(ref);

                sp += increment;
                i += increment;
            }
        }
    }

    BufferDestroy(value);
}
示例#4
0
文件: expand.c 项目: kkaempf/core
/**
 * Expand a #string into Buffer #out, returning the pointer to the string
 * itself, inside the Buffer #out. If #out is NULL then the buffer will be
 * created and destroyed internally.
 *
 * @retval NULL something went wrong
 */
char *ExpandScalar(const EvalContext *ctx, const char *ns, const char *scope,
                   const char *string, Buffer *out)
{
    bool out_belongs_to_us = false;

    if (out == NULL)
    {
        out               = BufferNew();
        out_belongs_to_us = true;
    }

    assert(string != NULL);
    assert(out != NULL);
    Buffer *current_item = BufferNew();

    for (const char *sp = string; *sp != '\0'; sp++)
    {
        BufferClear(current_item);
        ExtractScalarPrefix(current_item, sp, strlen(sp));

        BufferAppend(out, BufferData(current_item), BufferSize(current_item));
        sp += BufferSize(current_item);
        if (*sp == '\0')
        {
            break;
        }

        BufferClear(current_item);
        char varstring = sp[1];
        ExtractScalarReference(current_item,  sp, strlen(sp), true);
        sp += BufferSize(current_item) + 2;

        if (IsCf3VarString(BufferData(current_item)))
        {
            Buffer *temp = BufferCopy(current_item);
            BufferClear(current_item);
            ExpandScalar(ctx, ns, scope, BufferData(temp), current_item);
            BufferDestroy(temp);
        }

        if (!IsExpandable(BufferData(current_item)))
        {
            VarRef *ref = VarRefParseFromNamespaceAndScope(
                BufferData(current_item),
                ns, scope, CF_NS, '.');
            DataType value_type;
            const void *value = EvalContextVariableGet(ctx, ref, &value_type);
            VarRefDestroy(ref);

            switch (DataTypeToRvalType(value_type))
            {
            case RVAL_TYPE_SCALAR:
                assert(value != NULL);
                BufferAppendString(out, value);
                continue;
                break;

            case RVAL_TYPE_CONTAINER:
            {
                assert(value != NULL);
                const JsonElement *jvalue = value;      /* instead of casts */
                if (JsonGetElementType(jvalue) == JSON_ELEMENT_TYPE_PRIMITIVE)
                {
                    BufferAppendString(out, JsonPrimitiveGetAsString(jvalue));
                    continue;
                }
                break;
            }
            default:
                /* TODO Log() */
                break;
            }
        }

        if (varstring == '{')
        {
            BufferAppendF(out, "${%s}", BufferData(current_item));
        }
        else
        {
            BufferAppendF(out, "$(%s)", BufferData(current_item));
        }
    }

    BufferDestroy(current_item);

    LogDebug(LOG_MOD_EXPAND, "ExpandScalar( %s : %s . %s )  =>  %s",
             SAFENULL(ns), SAFENULL(scope), string, BufferData(out));

    return out_belongs_to_us ? BufferClose(out) : BufferGet(out);
}
示例#5
0
文件: expand.c 项目: awsiv/core
bool ExpandScalar(const EvalContext *ctx,
                  const char *ns, const char *scope, const char *string,
                  Buffer *out)
{
    assert(string);
    if (strlen(string) == 0)
    {
        return true;
    }

    bool fully_expanded = true;

    Buffer *current_item = BufferNew();
    for (const char *sp = string; *sp != '\0'; sp++)
    {
        BufferClear(current_item);
        ExtractScalarPrefix(current_item, sp, strlen(sp));

        BufferAppend(out, BufferData(current_item), BufferSize(current_item));
        sp += BufferSize(current_item);
        if (*sp == '\0')
        {
            break;
        }

        BufferClear(current_item);
        char varstring = sp[1];
        ExtractScalarReference(current_item,  sp, strlen(sp), true);
        sp += BufferSize(current_item) + 2;

        if (IsCf3VarString(BufferData(current_item)))
        {
            Buffer *temp = BufferCopy(current_item);
            BufferClear(current_item);
            ExpandScalar(ctx, ns, scope, BufferData(temp), current_item);
            BufferDestroy(temp);
        }

        if (!IsExpandable(BufferData(current_item)))
        {
            DataType type = CF_DATA_TYPE_NONE;
            const void *value = NULL;
            {
                VarRef *ref = VarRefParseFromNamespaceAndScope(BufferData(current_item), ns, scope, CF_NS, '.');
                value = EvalContextVariableGet(ctx, ref, &type);
                VarRefDestroy(ref);
            }

            if (value)
            {
                switch (DataTypeToRvalType(type))
                {
                case RVAL_TYPE_SCALAR:
                    BufferAppendString(out, value);
                    continue;

                case RVAL_TYPE_CONTAINER:
                    if (JsonGetElementType((JsonElement*)value) == JSON_ELEMENT_TYPE_PRIMITIVE)
                    {
                        BufferAppendString(out, JsonPrimitiveGetAsString((JsonElement*)value));
                        continue;
                    }
                    break;

                default:
                    break;
                }
            }
        }

        if (varstring == '{')
        {
            BufferAppendF(out, "${%s}", BufferData(current_item));
        }
        else
        {
            BufferAppendF(out, "$(%s)", BufferData(current_item));
        }
    }

    BufferDestroy(current_item);

    return fully_expanded;
}