示例#1
0
static void test_zeroBuffer(void)
{
    char *element0 = xstrdup("element0");
    unsigned int element0size = strlen(element0);
    const char *element0pointer = NULL;

    Buffer *buffer = BufferNew();
    assert_int_equal(element0size, BufferSet(buffer, element0, element0size));
    element0pointer = buffer->buffer;
    assert_int_equal(element0size, buffer->used);
    assert_int_equal(element0size, BufferSize(buffer));
    BufferZero(buffer);
    assert_int_equal(DEFAULT_BUFFER_SIZE, buffer->capacity);
    assert_int_equal(0, buffer->used);
    assert_int_equal(0, BufferSize(buffer));
	const char *data = BufferData(buffer);
	assert_string_equal(data, "");
    assert_true(element0pointer == buffer->buffer);
    BufferZero(NULL);
    assert_int_equal(0, BufferDestroy(&buffer));
    /*
     * Release the resources
     */
    BufferDestroy(&buffer);
    free (element0);
}
示例#2
0
static void test_zeroBuffer(void **state)
{
    char element0[] = "element0";
    unsigned int element0size = strlen(element0);
    const char *element0pointer = NULL;

    Buffer *buffer = NULL;
    assert_int_equal(0, BufferNew(&buffer));
    assert_int_equal(element0size, BufferSet(buffer, element0, element0size));
    element0pointer = buffer->buffer;
    assert_int_equal(element0size, buffer->used);
    assert_int_equal(element0size, BufferSize(buffer));
    BufferZero(buffer);
    assert_int_equal(DEFAULT_BUFFER_SIZE, buffer->capacity);
    assert_int_equal(0, buffer->used);
    assert_int_equal(0, BufferSize(buffer));
    assert_true(element0pointer == buffer->buffer);
    BufferZero(NULL);
    assert_int_equal(0, BufferDestroy(&buffer));
}
示例#3
0
文件: expand.c 项目: rcorrieri/core
static PromiseResult ExpandPromiseAndDo(EvalContext *ctx, const Promise *pp,
                                        Rlist *lists, Rlist *containers,
                                        PromiseActuator *ActOnPromise, void *param)
{
    const char *handle = PromiseGetHandle(pp);

    EvalContextStackPushPromiseFrame(ctx, pp, true);

    PromiseIterator *iter_ctx = NULL;
    size_t i = 0;
    PromiseResult result = PROMISE_RESULT_NOOP;
    Buffer *expbuf = BufferNew();
    for (iter_ctx = PromiseIteratorNew(ctx, pp, lists, containers); PromiseIteratorHasMore(iter_ctx); i++, PromiseIteratorNext(iter_ctx))
    {
        if (handle)
        {
            // This ordering is necessary to get automated canonification
            BufferZero(expbuf);
            ExpandScalar(ctx, NULL, "this", handle, expbuf);
            CanonifyNameInPlace(BufferGet(expbuf));
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "handle", BufferData(expbuf), CF_DATA_TYPE_STRING, "source=promise");
        }
        else
        {
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "handle", PromiseID(pp), CF_DATA_TYPE_STRING, "source=promise");
        }

        const Promise *pexp = EvalContextStackPushPromiseIterationFrame(ctx, i, iter_ctx);
        PromiseResult iteration_result = ActOnPromise(ctx, pexp, param);
        result = PromiseResultUpdate(result, iteration_result);

        if (strcmp(pp->parent_promise_type->name, "vars") == 0 || strcmp(pp->parent_promise_type->name, "meta") == 0)
        {
            VerifyVarPromise(ctx, pexp, true);
        }

        EvalContextStackPopFrame(ctx);
    }

    BufferDestroy(expbuf);
    PromiseIteratorDestroy(iter_ctx);
    EvalContextStackPopFrame(ctx);

    return result;
}
示例#4
0
static void test_vprintf(void)
{
    char *char0 = xstrdup("char0");
    unsigned int char0size = strlen(char0);
    const char *char0pointer = NULL;
    char *char1 = xstrdup("char1");
    unsigned int char1size = strlen(char1);
    const char *char1pointer = NULL;
    char *char2 = (char *)xmalloc(2 * DEFAULT_BUFFER_SIZE + 2);
    unsigned int char2size = 2 * DEFAULT_BUFFER_SIZE + 1;
    int int0 = 123456789;
    char *int0char = xstrdup("123456789");
    unsigned int int0charsize = strlen(int0char);
    double double0 = 3.1415;
    char *double0char = xstrdup("3.1415");
    unsigned int double0charsize = strlen(double0char);
    char *char0int0char1double0 = xstrdup("char0 123456789 char1 3.1415");
    unsigned int char0int0char1double0size = strlen(char0int0char1double0);
    char *element3 = (char *)xmalloc(DEFAULT_MEMORY_CAP * 2);
    unsigned int element3size = 2 * DEFAULT_MEMORY_CAP;

    Buffer *buffer = BufferNew();
    assert_true(buffer != NULL);
    /*
     * Print the first char and compare the result
     */
    assert_int_equal(char0size, test_vprintf_helper(buffer, "%s", char0));
    char0pointer = buffer->buffer;
    assert_string_equal(char0, buffer->buffer);
    assert_string_equal(char0, BufferData(buffer));
    assert_int_equal(char0size, buffer->used);
    assert_int_equal(char0size, BufferSize(buffer));
    /*
     * Overwrite the first char with the second one
     */
    assert_int_equal(char1size, test_vprintf_helper(buffer, "%s", char1));
    char1pointer = buffer->buffer;
    assert_string_equal(char1, buffer->buffer);
    assert_string_equal(char1, BufferData(buffer));
    assert_int_equal(char1size, buffer->used);
    assert_int_equal(char1size, BufferSize(buffer));
    assert_true(char0pointer == char1pointer);
    /*
     * Try the int now
     */
    assert_int_equal(int0charsize, test_vprintf_helper(buffer, "%d", int0));
    assert_string_equal(int0char, buffer->buffer);
    assert_string_equal(int0char, BufferData(buffer));
    assert_int_equal(int0charsize, buffer->used);
    assert_int_equal(int0charsize, BufferSize(buffer));
    /*
     * Try the double now
     */
    assert_int_equal(double0charsize, test_vprintf_helper(buffer, "%.4f", double0));
    assert_string_equal(double0char, buffer->buffer);
    assert_string_equal(double0char, BufferData(buffer));
    assert_int_equal(double0charsize, buffer->used);
    assert_int_equal(double0charsize, BufferSize(buffer));
    /*
     * Try the combination now
     */
    assert_int_equal(char0int0char1double0size, test_vprintf_helper(buffer, "%s %d %s %.4f", char0, int0, char1, double0));
    assert_string_equal(char0int0char1double0, buffer->buffer);
    assert_string_equal(char0int0char1double0, BufferData(buffer));
    assert_int_equal(char0int0char1double0size, buffer->used);
    assert_int_equal(char0int0char1double0size, BufferSize(buffer));
    /*
     * Finally, try something larger than the default buffer and see if we get the right return value.
     */
    unsigned int i = 0;
    for (i = 0; i < char2size; ++i)
        char2[i] = 'a';
    char2[char2size] = '\0';
    // The buffer should resize itself
    assert_int_equal(char2size, test_vprintf_helper(buffer, "%s", char2));
    assert_string_equal(char2, buffer->buffer);
    assert_string_equal(char2, BufferData(buffer));
    assert_int_equal(char2size, buffer->used);
    assert_int_equal(char2size, BufferSize(buffer));
    /*
     * A buffer that is so large that it will get rejected by our memory cap
     */
    BufferZero(buffer);
    for (i = 0; i < element3size; ++i)
    {
        element3[i] = 'b';
    }
    element3[element3size - 1] = '\0';
    assert_int_equal(-1, test_vprintf_helper(buffer, "%s", element3));
    /*
     * Boundary checks, BUFFER_SIZE-1, BUFFER_SIZE and BUFFER_SIZE+1
     */
    Buffer *bm1 = BufferNew();
    Buffer *be = BufferNew();
    Buffer *bp1 = BufferNew();
    /*
     * The sizes are different for printf. If we have a size of X, then the string
     * is of length X-1, and so forth.
     */
    char buffer_m1[DEFAULT_BUFFER_SIZE];
    char buffer_0[DEFAULT_BUFFER_SIZE + 1];
    char buffer_p1[DEFAULT_BUFFER_SIZE + 2];
    unsigned int bm1_size = DEFAULT_BUFFER_SIZE - 1;
    unsigned int be_size = DEFAULT_BUFFER_SIZE;
    unsigned int bp1_size = DEFAULT_BUFFER_SIZE + 1;
    /*
     * Make sure the buffers are filled with 0.
     */
    memset(buffer_m1, '\0', DEFAULT_BUFFER_SIZE);
    memset(buffer_0, '\0', DEFAULT_BUFFER_SIZE + 1);
    memset(buffer_p1, '\0', DEFAULT_BUFFER_SIZE + 2);
    /*
     * Write something to the buffers
     */
    memset(buffer_m1, 'c', DEFAULT_BUFFER_SIZE);
    memset(buffer_0, 'd', DEFAULT_BUFFER_SIZE + 1);
    memset(buffer_p1, 'e', DEFAULT_BUFFER_SIZE + 2);
    /*
     * One shorter, that means the buffer remains the same size as before.
     */
    buffer_m1[DEFAULT_BUFFER_SIZE - 1] = '\0';
    assert_int_equal(bm1_size, test_vprintf_helper(bm1, "%s", buffer_m1));
    assert_string_equal(buffer_m1, bm1->buffer);
    assert_int_equal(bm1->capacity, DEFAULT_BUFFER_SIZE);
    /*
     * Same size, it should allocate one more block.
     * This means retrying the operation.
     */
    buffer_0[DEFAULT_BUFFER_SIZE] = '\0';
    assert_int_equal(be_size, test_vprintf_helper(be, "%s", buffer_0));
    assert_string_equal(buffer_0, be->buffer);
    assert_int_equal(be->capacity, 2 * DEFAULT_BUFFER_SIZE);
    /*
     * 1 more, it should allocate one more block
     * This means retrying the operation.
     */
    buffer_p1[DEFAULT_BUFFER_SIZE + 1] = '\0';
    assert_int_equal(bp1_size, test_vprintf_helper(bp1, "%s", buffer_p1));
    assert_string_equal(buffer_p1, bp1->buffer);
    assert_int_equal(bp1->capacity, 2 * DEFAULT_BUFFER_SIZE);
    /*
     * Release the resources
     */
    BufferDestroy(&buffer);
    BufferDestroy(&bm1);
    BufferDestroy(&be);
    BufferDestroy(&bp1);
    free (char0);
    free (char1);
    free (char2);
    free (int0char);
    free (double0char);
    free (char0int0char1double0);
    free (element3);
}
示例#5
0
static void test_setBuffer(void)
{
    char *element0 = xstrdup("element0");
    unsigned int element0size = strlen(element0);
    char *element1 = (char *)xmalloc(2 * DEFAULT_BUFFER_SIZE + 2);
    unsigned int element1size = 2 * DEFAULT_BUFFER_SIZE + 1;
    char *element2 = (char *)xmalloc(DEFAULT_MEMORY_CAP * 2);
    unsigned int element2size = 2 * DEFAULT_MEMORY_CAP;

    Buffer *buffer = BufferNew();
    assert_true(buffer != NULL);
    // Smaller than the allocated buffer
    assert_int_equal(element0size, BufferSet(buffer, element0, element0size));
    assert_int_equal(element0size, buffer->used);
    assert_int_equal(element0size, BufferSize(buffer));
    assert_string_equal(element0, buffer->buffer);
    assert_string_equal(element0, BufferData(buffer));
    assert_int_equal(DEFAULT_BUFFER_SIZE, buffer->capacity);
    // Larger than the allocated buffer
    int i = 0;
    for (i = 0; i < element1size; ++i)
        element1[i] = 'a';
    element1[element1size] = '\0';
    assert_int_equal(element1size, BufferSet(buffer, element1, element1size));
    assert_int_equal(element1size, buffer->used);
    assert_string_equal(element1, buffer->buffer);
    assert_string_equal(element1, BufferData(buffer));
    assert_int_equal(DEFAULT_BUFFER_SIZE * 3, buffer->capacity);
    /*
     * A buffer that is so large that it will get rejected by our memory cap
     */
    BufferZero(buffer);
    for (i = 0; i < element2size; ++i)
    {
        element2[i] = 'b';
    }
    element2[element2size - 1] = '\0';
    assert_int_equal(-1, BufferSet(buffer, element2, element2size));
    /*
     * Boundary checks, BUFFER_SIZE-1, BUFFER_SIZE and BUFFER_SIZE+1
     */
    Buffer *bm1 = BufferNew();
    Buffer *be = BufferNew();
    Buffer *bp1 = BufferNew();
    char buffer_m1[DEFAULT_BUFFER_SIZE - 1];
    char buffer_0[DEFAULT_BUFFER_SIZE];
    char buffer_p1[DEFAULT_BUFFER_SIZE + 1];
    unsigned int bm1_size = DEFAULT_BUFFER_SIZE - 1;
    unsigned int be_size = DEFAULT_BUFFER_SIZE;
    unsigned int bp1_size = DEFAULT_BUFFER_SIZE + 1;
    for (i = 0; i < DEFAULT_BUFFER_SIZE - 1; ++i)
    {
        buffer_m1[i] = 'c';
        buffer_0[i] = 'd';
        buffer_p1[i] = 'e';
    }
    /*
     * One shorter, that means the buffer remains the same size as before.
     */
    buffer_m1[DEFAULT_BUFFER_SIZE - 2] = '\0';
    assert_int_equal(bm1_size, BufferSet(bm1, buffer_m1, bm1_size));
    assert_int_equal(bm1->capacity, DEFAULT_BUFFER_SIZE);
    /*
     * Same size, it should allocate one more block
     */
    buffer_0[DEFAULT_BUFFER_SIZE - 1] = '\0';
    assert_int_equal(be_size, BufferSet(be, buffer_0, be_size));
    assert_int_equal(be->capacity, 2 * DEFAULT_BUFFER_SIZE);
    /*
     * 1 more, it should allocate one more block
     */
    buffer_p1[DEFAULT_BUFFER_SIZE] = '\0';
    assert_int_equal(bp1_size, BufferSet(bp1, buffer_p1, bp1_size));
    assert_int_equal(bp1->capacity, 2 * DEFAULT_BUFFER_SIZE);
    // Negative cases
    assert_int_equal(-1, BufferSet(NULL, element0, element0size));
    assert_int_equal(-1, BufferSet(NULL, NULL, element0size));
    assert_int_equal(-1, BufferSet(buffer, NULL, element0size));
    assert_int_equal(0, BufferSet(buffer, element0, 0));
    /*
     * Destroy the buffer and good night.
     */
    assert_int_equal(0, BufferDestroy(&buffer));
    assert_true(buffer == NULL);
    BufferDestroy(&bm1);
    BufferDestroy(&be);
    BufferDestroy(&bp1);
    free (element0);
    free (element1);
    free (element2);
}
示例#6
0
static void test_appendBuffer(void)
{
    char *element0 = xstrdup("element0");
    unsigned int element0size = strlen(element0);
    const char *element0pointer = NULL;
    char *element1 = xstrdup("element1");
    unsigned int element1size = strlen(element1);
    const char *element1pointer = NULL;
    char *element2 = (char *)xmalloc(2 * DEFAULT_BUFFER_SIZE + 2);
    unsigned int element2size = 2 * DEFAULT_BUFFER_SIZE + 1;
    char *element3 = (char *)xmalloc(DEFAULT_MEMORY_CAP * 2);
    unsigned int element3size = 2 * DEFAULT_MEMORY_CAP;

    Buffer *buffer = BufferNew();
    assert_true(buffer != NULL);
    // Initialize the buffer with a small string
    assert_int_equal(element0size, BufferAppend(buffer, element0, element0size));
    element0pointer = buffer->buffer;
    assert_int_equal(element0size, buffer->used);
    assert_int_equal(element0size, BufferSize(buffer));
    assert_string_equal(element0, buffer->buffer);
    assert_string_equal(element0, BufferData(buffer));
    assert_int_equal(DEFAULT_BUFFER_SIZE, buffer->capacity);
    // Attach a small string to it
    assert_int_equal(element0size + element1size, BufferAppend(buffer, element1, element1size));
    element1pointer = buffer->buffer;
    assert_true(element0pointer == element1pointer);
    assert_int_equal(buffer->used, element0size + element1size);
    assert_int_equal(BufferSize(buffer), element0size + element1size);
    char *shortAppend = NULL;
    shortAppend = (char *)xmalloc(element0size + element1size + 1);
    strcpy(shortAppend, element0);
    strcat(shortAppend, element1);
    assert_string_equal(shortAppend, buffer->buffer);
    assert_string_equal(shortAppend, BufferData(buffer));

    /*
     * Zero the string and start again.
     */
    BufferZero(buffer);
    assert_int_equal(element0size, BufferAppend(buffer, element0, element0size));
    element0pointer = buffer->buffer;
    assert_int_equal(element0size, buffer->used);
    assert_int_equal(element0size, BufferSize(buffer));
    assert_string_equal(element0, buffer->buffer);
    assert_string_equal(element0, BufferData(buffer));

    /*
     * Larger than the allocated buffer, this means we will allocate more memory
     * copy stuff into the new buffer and all that.
     */
    int i = 0;
    for (i = 0; i < element2size; ++i)
        element2[i] = 'a';
    element2[element2size] = '\0';
    assert_int_equal(element0size + element2size, BufferAppend(buffer, element2, element2size));
    assert_int_equal(buffer->used, element0size + element2size);
    assert_int_equal(BufferSize(buffer), element0size + element2size);
    char *longAppend = NULL;
    longAppend = (char *)xmalloc(element0size + element2size + 1);
    strcpy(longAppend, element0);
    strcat(longAppend, element2);
    assert_string_equal(longAppend, buffer->buffer);
    assert_string_equal(longAppend, BufferData(buffer));
    /*
     * A buffer that is so large that it will get rejected by our memory cap
     */
    BufferZero(buffer);
    for (i = 0; i < element3size; ++i)
    {
        element3[i] = 'b';
    }
    element3[element3size - 1] = '\0';
    assert_int_equal(-1, BufferAppend(buffer, element3, element3size));
    /*
     * Boundary checks, BUFFER_SIZE-1, BUFFER_SIZE and BUFFER_SIZE+1
     */
    Buffer *bm1 = BufferNew();
    Buffer *be = BufferNew();
    Buffer *bp1 = BufferNew();
    char buffer_m1[DEFAULT_BUFFER_SIZE - 1];
    char buffer_0[DEFAULT_BUFFER_SIZE];
    char buffer_p1[DEFAULT_BUFFER_SIZE + 1];
    unsigned int bm1_size = DEFAULT_BUFFER_SIZE - 1;
    unsigned int be_size = DEFAULT_BUFFER_SIZE;
    unsigned int bp1_size = DEFAULT_BUFFER_SIZE + 1;
    for (i = 0; i < DEFAULT_BUFFER_SIZE - 1; ++i)
    {
        buffer_m1[i] = 'c';
        buffer_0[i] = 'd';
        buffer_p1[i] = 'e';
    }
    /*
     * One shorter, that means the buffer remains the same size as before.
     */
    buffer_m1[DEFAULT_BUFFER_SIZE - 2] = '\0';
    assert_int_equal(bm1_size, BufferAppend(bm1, buffer_m1, bm1_size));
    assert_int_equal(bm1->capacity, DEFAULT_BUFFER_SIZE);
    /*
     * Same size, it should allocate one more block
     */
    buffer_0[DEFAULT_BUFFER_SIZE - 1] = '\0';
    assert_int_equal(be_size, BufferAppend(be, buffer_0, be_size));
    assert_int_equal(be->capacity, 2 * DEFAULT_BUFFER_SIZE);
    /*
     * 1 more, it should allocate one more block
     */
    buffer_p1[DEFAULT_BUFFER_SIZE] = '\0';
    assert_int_equal(bp1_size, BufferAppend(bp1, buffer_p1, bp1_size));
    assert_int_equal(bp1->capacity, 2 * DEFAULT_BUFFER_SIZE);
    /*
     * Destroy the buffer and good night.
     */
    free(shortAppend);
    free(longAppend);
    assert_int_equal(0, BufferDestroy(&buffer));
    assert_int_equal(0, BufferDestroy(&bm1));
    assert_int_equal(0, BufferDestroy(&be));
    assert_int_equal(0, BufferDestroy(&bp1));
    free (element0);
    free (element1);
    free (element2);
    free (element3);
}
示例#7
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;
}
示例#8
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);
}
示例#9
0
int LoadFileAsItemList(Item **liststart, const char *file, EditDefaults edits)
{
    {
        struct stat statbuf;
        if (stat(file, &statbuf) == -1)
        {
            Log(LOG_LEVEL_VERBOSE, "The proposed file '%s' could not be loaded. (stat: %s)", file, GetErrorStr());
            return false;
        }

        if (edits.maxfilesize != 0 && statbuf.st_size > edits.maxfilesize)
        {
            Log(LOG_LEVEL_INFO, "File '%s' is bigger than the limit edit.max_file_size = %jd > %d bytes", file,
                  (intmax_t) statbuf.st_size, edits.maxfilesize);
            return (false);
        }

        if (!S_ISREG(statbuf.st_mode))
        {
            Log(LOG_LEVEL_INFO, "%s is not a plain file", file);
            return false;
        }
    }

    FILE *fp = safe_fopen(file, "r");
    if (!fp)
    {
        Log(LOG_LEVEL_INFO, "Couldn't read file '%s' for editing. (fopen: %s)", file, GetErrorStr());
        return false;
    }

    Buffer *concat = BufferNew();

    size_t line_size = CF_BUFSIZE;
    char *line = xmalloc(line_size);
    bool result = true;

    for (;;)
    {
        ssize_t num_read = CfReadLine(&line, &line_size, fp);
        if (num_read == -1)
        {
            if (!feof(fp))
            {
                Log(LOG_LEVEL_ERR,
                    "Unable to read contents of '%s'. (fread: %s)",
                    file, GetErrorStr());
                result = false;
            }
            break;
        }

        if (edits.joinlines && *(line + strlen(line) - 1) == '\\')
        {
            *(line + strlen(line) - 1) = '\0';

            BufferAppend(concat, line, num_read);
        }
        else
        {
            BufferAppend(concat, line, num_read);
            if (!feof(fp) || (BufferSize(concat) > 0))
            {
                AppendItem(liststart, BufferData(concat), NULL);
            }
        }

        BufferZero(concat);
    }

    free(line);
    BufferDestroy(concat);
    fclose(fp);
    return result;
}
示例#10
0
VarRef *VarRefParseFromNamespaceAndScope(const char *qualified_name, const char *_ns, const char *_scope, char ns_separator, char scope_separator)
{
    char *ns = NULL;

    const char *indices_start = strchr(qualified_name, '[');

    const char *scope_start = strchr(qualified_name, ns_separator);
    if (scope_start && (!indices_start || scope_start < indices_start))
    {
        ns = xstrndup(qualified_name, scope_start - qualified_name);
        scope_start++;
    }
    else
    {
        scope_start = qualified_name;
    }

    char *scope = NULL;

    const char *lval_start = strchr(scope_start, scope_separator);

    if (lval_start && (!indices_start || lval_start < indices_start))
    {
        lval_start++;
        scope = xstrndup(scope_start, lval_start - scope_start - 1);
    }
    else
    {
        lval_start = scope_start;
    }

    char *lval = NULL;
    char **indices = NULL;
    size_t num_indices = 0;

    if (indices_start)
    {
        indices_start++;
        lval = xstrndup(lval_start, indices_start - lval_start - 1);

        assert("Index brackets in variable expression did not balance" && IndexBracketsBalance(indices_start - 1));

        num_indices = IndexCount(indices_start - 1);
        indices = xmalloc(num_indices * sizeof(char *));

        Buffer *buf = BufferNew();
        size_t cur_index = 0;
        for (const char *c = indices_start; *c != '\0'; c++)
        {
            if (*c == '[')
            {
                cur_index++;
            }
            else if (*c == ']')
            {
                indices[cur_index] = xstrdup(BufferData(buf));
                BufferZero(buf);
            }
            else
            {
                BufferAppend(buf, c, sizeof(char));
            }
        }
        BufferDestroy(&buf);
    }
    else
    {
        lval = xstrdup(lval_start);
    }

    assert(lval);

    if (!scope && !_scope)
    {
        assert(ns == NULL && "A variable missing a scope should not have a namespace");
    }

    VarRef *ref = xmalloc(sizeof(VarRef));

    ref->ns = ns ? ns : (_ns ? xstrdup(_ns) : NULL);
    ref->scope = scope ? scope : (_scope ? xstrdup(_scope) : NULL);
    ref->lval = lval;
    ref->indices = indices;
    ref->num_indices = num_indices;

    ref->hash = VarRefHash(ref);

    return ref;
}