示例#1
0
文件: mustache.c 项目: amousset/core
static JsonElement *LookupVariable(Seq *hash_stack, const char *name, size_t name_len)
{
    assert(SeqLength(hash_stack) > 0);

    size_t num_comps = StringCountTokens(name, name_len, ".");

    JsonElement *base_var = NULL;
    {
        StringRef base_comp = StringGetToken(name, name_len, 0, ".");
        char *base_comp_str = xstrndup(base_comp.data, base_comp.len);

        for (ssize_t i = SeqLength(hash_stack) - 1; i >= 0; i--)
        {
            JsonElement *hash = SeqAt(hash_stack, i);
            if (!hash)
            {
                continue;
            }

            if (JsonGetElementType(hash) == JSON_ELEMENT_TYPE_CONTAINER && JsonGetContainerType(hash) == JSON_CONTAINER_TYPE_OBJECT)
            {
                JsonElement *var = JsonObjectGet(hash, base_comp_str);
                if (var)
                {
                    base_var = var;
                    break;
                }
            }
        }
        free(base_comp_str);
    }

    if (!base_var)
    {
        return NULL;
    }

    for (size_t i = 1; i < num_comps; i++)
    {
        if (JsonGetElementType(base_var) != JSON_ELEMENT_TYPE_CONTAINER || JsonGetContainerType(base_var) != JSON_CONTAINER_TYPE_OBJECT)
        {
            return NULL;
        }

        StringRef comp = StringGetToken(name, name_len, i, ".");
        char *comp_str = xstrndup(comp.data, comp.len);
        base_var = JsonObjectGet(base_var, comp_str);
        free(comp_str);

        if (!base_var)
        {
            return NULL;
        }
    }

    assert(base_var);
    return base_var;
}
示例#2
0
文件: json_test.c 项目: ajlill/core
static void test_parse_empty_containers(void)
{
    {
        const char *data = "{}";
        JsonElement *obj = NULL;
        assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &obj));
        assert_true(obj != NULL);
        assert_int_equal(JSON_ELEMENT_TYPE_CONTAINER, JsonGetElementType(obj));
        assert_int_equal(JSON_CONTAINER_TYPE_OBJECT, JsonGetContainerType(obj));
        assert_int_equal(0, JsonLength(obj));
        JsonDestroy(obj);
    }

    {
        const char *data = "[]";
        JsonElement *arr = NULL;
        assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &arr));
        assert_true(arr != NULL);
        assert_int_equal(JSON_ELEMENT_TYPE_CONTAINER, JsonGetElementType(arr));
        assert_int_equal(JSON_CONTAINER_TYPE_ARRAY, JsonGetContainerType(arr));
        assert_int_equal(0, JsonLength(arr));
        JsonDestroy(arr);
    }
}
示例#3
0
文件: json_test.c 项目: ajlill/core
static void test_select(void)
{
    const char *data = OBJECT_ARRAY;
    JsonElement *obj = NULL;
    assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &obj));

    assert_true(obj == JsonSelect(obj, 0, NULL));

    {
        char *indices[] = { "first" };
        assert_int_equal(JSON_CONTAINER_TYPE_ARRAY, JsonGetContainerType(JsonSelect(obj, 1, indices)));
    }
    {
        char *indices[] = { "first", "0" };
        assert_string_equal("one", JsonPrimitiveGetAsString(JsonSelect(obj, 2, indices)));
    }
    {
        char *indices[] = { "first", "1" };
        assert_string_equal("two", JsonPrimitiveGetAsString(JsonSelect(obj, 2, indices)));
    }
    {
        char *indices[] = { "first", "2" };
        assert_true(JsonSelect(obj, 2, indices) == NULL);
    }
    {
        char *indices[] = { "first", "x" };
        assert_true(JsonSelect(obj, 2, indices) == NULL);
    }

    {
        char *indices[] = { "first", "0", "x" };
        assert_true(JsonSelect(obj, 3, indices) == NULL);
    }

    {
        char *indices[] = { "second" };
        assert_true(JsonSelect(obj, 1, indices) == NULL);
    }

    JsonDestroy(obj);
}
示例#4
0
文件: mustache.c 项目: amousset/core
static bool Render(Buffer *out, const char *start, const char *input, Seq *hash_stack,
                   char *delim_start, size_t *delim_start_len,
                   char *delim_end, size_t *delim_end_len,
                   bool skip_content,
                   const char *section,
                   const char **section_end)
{
    while (true)
    {
        if (!input)
        {
            Log(LOG_LEVEL_ERR, "Unexpected end to Mustache template");
            return false;
        }

        Mustache tag = NextTag(input, delim_start, *delim_start_len, delim_end, *delim_end_len);

        {
            const char *line_begin = NULL;
            const char *line_end = NULL;
            if (!IsTagTypeRenderable(tag.type) && IsTagStandalone(start, tag.begin, tag.end, &line_begin, &line_end))
            {
                RenderContent(out, input, line_begin - input, false, skip_content);
                input = line_end;
            }
            else
            {
                RenderContent(out, input, tag.begin - input, false, skip_content);
                input = tag.end;
            }
        }

        switch (tag.type)
        {
        case TAG_TYPE_ERR:
            return false;

        case TAG_TYPE_DELIM:
            if (!SetDelimiters(tag.content, tag.content_len,
                               delim_start, delim_start_len,
                               delim_end, delim_end_len))
            {
                return false;
            }
            continue;

        case TAG_TYPE_COMMENT:
            continue;

        case TAG_TYPE_NONE:
            return true;

        case TAG_TYPE_VAR_SERIALIZED:
        case TAG_TYPE_VAR_SERIALIZED_COMPACT:
        case TAG_TYPE_VAR_UNESCAPED:
        case TAG_TYPE_VAR:
            if (!skip_content)
            {
                if (tag.content_len > 0)
                {
                    if (!RenderVariable(out, tag.content, tag.content_len, tag.type, hash_stack))
                    {
                        return false;
                    }
                }
                else
                {
                    RenderContent(out, delim_start, *delim_start_len, false, false);
                    RenderContent(out, delim_end, *delim_end_len, false, false);
                }
            }
            continue;

        case TAG_TYPE_INVERTED:
        case TAG_TYPE_SECTION:
            {
                char *section = xstrndup(tag.content, tag.content_len);
                JsonElement *var = LookupVariable(hash_stack, tag.content, tag.content_len);
                SeqAppend(hash_stack, var);

                if (!var)
                {
                    const char *cur_section_end = NULL;
                    if (!Render(out, start, input, hash_stack, delim_start, delim_start_len, delim_end, delim_end_len,
                                skip_content || tag.type != TAG_TYPE_INVERTED, section, &cur_section_end))
                    {
                        free(section);
                        return false;
                    }
                    free(section);
                    input = cur_section_end;
                    continue;
                }

                switch (JsonGetElementType(var))
                {
                case JSON_ELEMENT_TYPE_PRIMITIVE:
                    switch (JsonGetPrimitiveType(var))
                    {
                    case JSON_PRIMITIVE_TYPE_BOOL:
                        {
                            bool skip = skip_content || (!JsonPrimitiveGetAsBool(var) ^ (tag.type == TAG_TYPE_INVERTED));

                            const char *cur_section_end = NULL;
                            if (!Render(out, start, input, hash_stack, delim_start, delim_start_len, delim_end, delim_end_len,
                                        skip, section, &cur_section_end))
                            {
                                free(section);
                                return false;
                            }
                            free(section);
                            input = cur_section_end;
                        }
                        continue;

                    default:
                        Log(LOG_LEVEL_WARNING, "Mustache sections can only take a boolean or a container (array or map) value, but section '%s' isn't getting one of those.",
                            section);
                        return false;
                    }
                    break;

                case JSON_ELEMENT_TYPE_CONTAINER:
                    switch (JsonGetContainerType(var))
                    {
                    case JSON_CONTAINER_TYPE_OBJECT:
                    case JSON_CONTAINER_TYPE_ARRAY:
                        if (JsonLength(var) > 0)
                        {
                            const char *cur_section_end = NULL;
                            for (size_t i = 0; i < JsonLength(var); i++)
                            {
                                JsonElement *child_hash = JsonAt(var, i);
                                SeqAppend(hash_stack, child_hash);


                                if (!Render(out, start, input,
                                            hash_stack,
                                            delim_start, delim_start_len, delim_end, delim_end_len,
                                            skip_content || tag.type == TAG_TYPE_INVERTED, section, &cur_section_end))
                                {
                                    free(section);
                                    return false;
                                }
                            }
                            input = cur_section_end;
                            free(section);
                        }
                        else
                        {
                            const char *cur_section_end = NULL;
                            if (!Render(out, start, input, hash_stack, delim_start, delim_start_len, delim_end, delim_end_len,
                                        tag.type != TAG_TYPE_INVERTED, section, &cur_section_end))
                            {
                                free(section);
                                return false;
                            }
                            free(section);
                            input = cur_section_end;
                        }
                        break;
                    }
                    break;
                }
            }
            continue;
        case TAG_TYPE_SECTION_END:
            if (!section)
            {
                char *varname = xstrndup(tag.content, tag.content_len);
                Log(LOG_LEVEL_WARNING, "Unknown section close in mustache template '%s'", varname);
                free(varname);
                return false;
            }
            else
            {
                SeqRemove(hash_stack, SeqLength(hash_stack) - 1);
                *section_end = input;
                return true;
            }
            break;

        default:
            assert(false);
            return false;
        }
    }

    assert(false);
}