Ejemplo n.º 1
0
/**
 * 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);
}
Ejemplo n.º 2
0
Archivo: regex.c Proyecto: cstroe/core
// If return_names is not set, only the captured data is returned (so
// for N captures you can expect N elements in the Sequence).
Seq *StringMatchCapturesWithPrecompiledRegex(const pcre *pattern, const char *str, const bool return_names)
{
    int captures;
    int res = pcre_fullinfo(pattern, NULL, PCRE_INFO_CAPTURECOUNT, &captures);
    if (res != 0)
    {
        return NULL;
    }

    // Get the table of named captures.
    unsigned char *name_table = NULL; // Doesn't have to be freed as per docs.
    int namecount = 0;
    int name_entry_size = 0;
    unsigned char *tabptr;

    pcre_fullinfo(pattern, NULL, PCRE_INFO_NAMECOUNT, &namecount);

    const bool have_named_captures = (namecount > 0 && return_names);

    if (have_named_captures)
    {
        pcre_fullinfo(pattern, NULL, PCRE_INFO_NAMETABLE, &name_table);
        pcre_fullinfo(pattern, NULL, PCRE_INFO_NAMEENTRYSIZE, &name_entry_size);
    }

    int *ovector = xmalloc(sizeof(int) * (captures + 1) * 3);

    int result = pcre_exec(pattern, NULL, str, strlen(str),
                           0, 0, ovector, (captures + 1) * 3);

    if (result <= 0)
    {
        free(ovector);
        return NULL;
    }

    Seq *ret = SeqNew(captures + 1, BufferDestroy);
    for (int i = 0; i <= captures; ++i)
    {
        Buffer *capture = NULL;

        if (have_named_captures)
        {
            // The overhead of doing a nested name scan is negligible.
            tabptr = name_table;
            for (int namepos = 0; namepos < namecount; namepos++)
            {
                int n = (tabptr[0] << 8) | tabptr[1];
                if (n == i) // We found the position
                {
                    capture = BufferNewFrom(tabptr + 2, name_entry_size - 3);
                    break;
                }
                tabptr += name_entry_size;
            }
        }

        if (return_names)
        {
            if (NULL == capture)
            {
                capture = BufferNew();
                BufferAppendF(capture, "%zd", i);
            }

            SeqAppend(ret, capture);
        }

        Buffer *data = BufferNewFrom(str + ovector[2*i],
                                     ovector[2*i + 1] - ovector[2 * i]);
        Log(LOG_LEVEL_DEBUG, "StringMatchCaptures: return_names = %d, have_named_captures = %d, offset %d, name '%s', data '%s'", return_names, have_named_captures, i, capture == NULL ? "no_name" : BufferData(capture), BufferData(data));
        SeqAppend(ret, data);
    }

    free(ovector);
    return ret;
}
Ejemplo n.º 3
0
Archivo: expand.c Proyecto: 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;
}