Exemplo n.º 1
0
Arquivo: json.c Projeto: Akemi/mpv
static int json_append(bstr *b, const struct mpv_node *src, int indent)
{
    switch (src->format) {
    case MPV_FORMAT_NONE:
        APPEND(b, "null");
        return 0;
    case MPV_FORMAT_FLAG:
        APPEND(b, src->u.flag ? "true" : "false");
        return 0;
    case MPV_FORMAT_INT64:
        bstr_xappend_asprintf(NULL, b, "%"PRId64, src->u.int64);
        return 0;
    case MPV_FORMAT_DOUBLE:
        bstr_xappend_asprintf(NULL, b, "%f", src->u.double_);
        return 0;
    case MPV_FORMAT_STRING:
        write_json_str(b, src->u.string);
        return 0;
    case MPV_FORMAT_NODE_ARRAY:
    case MPV_FORMAT_NODE_MAP: {
        struct mpv_node_list *list = src->u.list;
        bool is_obj = src->format == MPV_FORMAT_NODE_MAP;
        APPEND(b, is_obj ? "{" : "[");
        int next_indent = indent >= 0 ? indent + 1 : -1;
        for (int n = 0; n < list->num; n++) {
            if (n)
                APPEND(b, ",");
            add_indent(b, next_indent);
            if (is_obj) {
                write_json_str(b, list->keys[n]);
                APPEND(b, ":");
            }
            json_append(b, &list->values[n], next_indent);
        }
        add_indent(b, indent);
        APPEND(b, is_obj ? "}" : "]");
        return 0;
    }
    }
    return -1; // unknown format
}
Exemplo n.º 2
0
struct Token* advance_token(int res, struct Token* current, int indent, struct TokenState* state, char* text, int ID_t, int DD_t, struct cTokenError* error) {
    int numlines = 0;
    int cindent;
    int last = state->at;
    int ind = 0;
    struct Token* tmp;
    int i;

    for (i=state->at; i < state->at + res; i++) {
        if (text[i] == '\n') {
            numlines += 1;
            last = i;
        }
    }
    state->lineno += numlines;
    if (numlines) {
        state->charno = state->at + res - last;
    } else {
        state->charno += res;
    }
    if (!indent || res != 1 || text[state->at] != '\n') {
        return current;
    }
    ind = t_white(state->at+1, text, state->ln);
    if (ind < 0) {
        return current;
    }
    cindent = state->indents[state->num_indents-1];
    if (ind > cindent) {
        add_indent(state, ind);
        tmp = (struct Token*)malloc(sizeof(struct Token));
        tmp->value = "";
        tmp->which = ID_t;
        tmp->next = NULL;
        tmp->lineno = state->lineno;
        tmp->charno = state->charno;
        current->next = tmp;
        current = tmp;
    } else if (ind < cindent) {
        while (ind < cindent) {
            state->num_indents -= 1;
            tmp = (struct Token*)malloc(sizeof(struct Token));
            tmp->value = "";
            tmp->which = DD_t;
            tmp->next = NULL;
            tmp->lineno = state->lineno;
            tmp->charno = state->charno;
            current->next = tmp;
            current = tmp;
            cindent = state->indents[state->num_indents - 1];
        }
        if (ind != cindent) {
            // etxt = "invalid indentation -- %d (expected %d)' % (ind, cindent)";
            error->text = "invalid indentation";
            error->lineno = state->lineno;
            error->charno = state->charno;
            // error->wanted = cindent;
            return NULL;
        }
    }
    return current;
}
Exemplo n.º 3
0
int serialize_tree(struct kowhai_node_t** desc, void** data, char* target_buffer, size_t target_size, int level, void* get_name_param, kowhai_get_symbol_name_t get_name, int in_union, int* largest_data_field)
{
    int target_offset = 0;
    struct kowhai_node_t* node;
    int i, chars;
    char* node_end_str;

    while (1)
    {
        node = *desc;

        if (node->type == KOW_BRANCH_END)
            return target_offset;

        // indent to current level using tabs
        chars = add_indent(&target_buffer, &target_size, &target_offset, level);
        if (chars < 0)
            return chars;

        //
        // write node
        //

        switch (node->type)
        {
            case KOW_BRANCH_START:
            case KOW_BRANCH_U_START:
            {
                int node_is_union = node->type == KOW_BRANCH_U_START;
                int largest_child_data_field = 0;
                void* initial_data = *data;
                // write header
                chars = add_header(&target_buffer, &target_size, &target_offset, node, get_name_param, get_name);
                if (chars < 0)
                    return chars;
                if (node->count > 1)
                {
                    struct kowhai_node_t* initial_node = *desc;
                    // write array identifier
                    chars = add_string(&target_buffer, &target_size, &target_offset, ", \""ARRAY"\": [\n");
                    if (chars < 0)
                    return chars;
                    for (i = 0; i < node->count; i++)
                    {
                        // set descriptor to initial node at the branch array
                        *desc = initial_node;
                        (*desc) += 1;
                        // indent to current level using tab
                        chars = add_indent(&target_buffer, &target_size, &target_offset, level + 1);
                        if (chars < 0)
                            return chars;
                        // write branch children start
                        chars = add_string(&target_buffer, &target_size, &target_offset, "[\n");
                        if (chars < 0)
                            return chars;
                        // write branch children
                        chars = serialize_tree(desc, data, target_buffer, target_size, level + 1, get_name_param, get_name, node_is_union, &largest_child_data_field);
                        if (chars < 0)
                            return chars;
                        target_offset += chars;
                        target_buffer += chars;
                        target_size -= chars;
                        // increment data pointer if node is a union
                        if (node_is_union)
                        {
                            *data = (char*)initial_data + largest_child_data_field;
                            initial_data = *data;
                        }
                        // indent to current level using tab
                        chars = add_indent(&target_buffer, &target_size, &target_offset, level + 1);
                        if (chars < 0)
                            return chars;
                        // write branch children end
                        chars = add_string(&target_buffer, &target_size, &target_offset, "]");
                        if (chars < 0)
                            return chars;
                        if (i < node->count - 1)
                        {
                            chars = add_string(&target_buffer, &target_size, &target_offset, ",\n");
                            if (chars < 0)
                                return chars;
                        }
                        else
                        {
                            chars = add_string(&target_buffer, &target_size, &target_offset, "\n");
                            if (chars < 0)
                                return chars;
                        }
                    }
                }
                else
                {
                    // write children identifier
                    chars = add_string(&target_buffer, &target_size, &target_offset, ", \""CHILDREN"\": [\n");
                    if (chars < 0)
                        return chars;
                    // write branch children
                    (*desc) += 1;
                    chars = serialize_tree(desc, data, target_buffer, target_size, level + 1, get_name_param, get_name, node_is_union, &largest_child_data_field);
                    if (chars < 0)
                        return chars;
                    target_offset += chars;
                    target_buffer += chars;
                    target_size -= chars;
                    // increment data pointer if node is a union
                    if (node_is_union)
                        *data = (char*)initial_data + largest_child_data_field;
                }
                // indent to current level using tab
                chars = add_indent(&target_buffer, &target_size, &target_offset, level);
                if (chars < 0)
                    return chars;
                // write node end
                if (level == 0 || (*desc)[1].type == KOW_BRANCH_END)
                    node_end_str = "]}\n";
                else
                    node_end_str = "]},\n";
                chars = add_string(&target_buffer, &target_size, &target_offset, node_end_str);
                if (chars < 0)
                    return chars;
                break;
            }
            default:
            {
                int value_size = kowhai_get_node_type_size(node->type);
                // write header
                chars = add_header(&target_buffer, &target_size, &target_offset, node, get_name_param, get_name);
                if (chars < 0)
                    return chars;
                // write value identifier
                chars = add_string(&target_buffer, &target_size, &target_offset, ", \""VALUE"\": ");
                if (chars < 0)
                    return chars;
                // write value/s
                if (node->type == KOW_CHAR && node->count > 1 && str_printable((char *)*data, node->count))
                {
                    // special string case
                    chars = write_string(target_buffer, target_size, "\"%.*s\"", node->count, (char*)*data);
                    if (chars >= 0)
                    {
                        target_buffer += chars;
                        target_size -= chars;
                        target_offset += chars;
                    }
                    else
                        return chars;
                    // increment data pointer
                    if (!in_union)
                        *data = (char*)*data + value_size * node->count;
                    else if (value_size * node->count > *largest_data_field)
                        *largest_data_field = value_size * node->count;
                }
                else if (node->count > 1)
                {
                    // write start bracket
                    chars = add_string(&target_buffer, &target_size, &target_offset, "[");
                    if (chars < 0)
                        return chars;
                    for (i = 0; i < node->count; i++)
                    {
                        // write leaf node array item value
                        chars = add_value(&target_buffer, &target_size, &target_offset, node->type, (char*)*data + i * value_size);
                        if (chars < 0)
                            return chars;
                        // write comma if there is another array item
                        if (i < node->count - 1)
                        {
                            chars = add_string(&target_buffer, &target_size, &target_offset, ", ");
                            if (chars < 0)
                                return chars;
                        }
                    }
                    // increment data pointer
                    if (!in_union)
                        *data = (char*)*data + value_size * node->count;
                    else if (value_size * node->count > *largest_data_field)
                        *largest_data_field = value_size * node->count;
                    // write end bracket
                    chars = add_string(&target_buffer, &target_size, &target_offset, "]");
                    if (chars < 0)
                        return chars;
                }
                else
                {
                    // write leaf node value
                    chars = add_value(&target_buffer, &target_size, &target_offset, node->type, *data);
                    if (chars < 0)
                        return chars;
                    // increment data pointer
                    if (!in_union)
                        *data = (char*)*data + value_size;
                    else if (value_size > *largest_data_field)
                        *largest_data_field = value_size;
                }
                // write node end
                if (level == 0 || node[1].type == KOW_BRANCH_END)
                    node_end_str = " }\n";
                else
                    node_end_str = " },\n";
                chars = add_string(&target_buffer, &target_size, &target_offset, node_end_str);
                if (chars < 0)
                    return chars;
                break;
            }
        }

        if (level == 0)
            return target_offset;

        (*desc) += 1;
    }
}
Exemplo n.º 4
0
/*
 * common worker for above two functions
 */
static char *
JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
{
	bool		first = true;
	JsonbIterator *it;
	JsonbValue	v;
	JsonbIteratorToken type = WJB_DONE;
	int			level = 0;
	bool		redo_switch = false;

	/* If we are indenting, don't add a space after a comma */
	int			ispaces = indent ? 1 : 2;

	/*
	 * Don't indent the very first item. This gets set to the indent flag at
	 * the bottom of the loop.
	 */
	bool		use_indent = false;
	bool		raw_scalar = false;
	bool		last_was_key = false;

	if (out == NULL)
		out = makeStringInfo();

	enlargeStringInfo(out, (estimated_len >= 0) ? estimated_len : 64);

	it = JsonbIteratorInit(in);

	while (redo_switch ||
		   ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE))
	{
		redo_switch = false;
		switch (type)
		{
			case WJB_BEGIN_ARRAY:
				if (!first)
					appendBinaryStringInfo(out, ", ", ispaces);

				if (!v.val.array.rawScalar)
				{
					add_indent(out, use_indent && !last_was_key, level);
					appendStringInfoCharMacro(out, '[');
				}
				else
					raw_scalar = true;

				first = true;
				level++;
				break;
			case WJB_BEGIN_OBJECT:
				if (!first)
					appendBinaryStringInfo(out, ", ", ispaces);

				add_indent(out, use_indent && !last_was_key, level);
				appendStringInfoCharMacro(out, '{');

				first = true;
				level++;
				break;
			case WJB_KEY:
				if (!first)
					appendBinaryStringInfo(out, ", ", ispaces);
				first = true;

				add_indent(out, use_indent, level);

				/* json rules guarantee this is a string */
				jsonb_put_escaped_value(out, &v);
				appendBinaryStringInfo(out, ": ", 2);

				type = JsonbIteratorNext(&it, &v, false);
				if (type == WJB_VALUE)
				{
					first = false;
					jsonb_put_escaped_value(out, &v);
				}
				else
				{
					Assert(type == WJB_BEGIN_OBJECT || type == WJB_BEGIN_ARRAY);

					/*
					 * We need to rerun the current switch() since we need to
					 * output the object which we just got from the iterator
					 * before calling the iterator again.
					 */
					redo_switch = true;
				}
				break;
			case WJB_ELEM:
				if (!first)
					appendBinaryStringInfo(out, ", ", ispaces);
				first = false;

				if (!raw_scalar)
					add_indent(out, use_indent, level);
				jsonb_put_escaped_value(out, &v);
				break;
			case WJB_END_ARRAY:
				level--;
				if (!raw_scalar)
				{
					add_indent(out, use_indent, level);
					appendStringInfoCharMacro(out, ']');
				}
				first = false;
				break;
			case WJB_END_OBJECT:
				level--;
				add_indent(out, use_indent, level);
				appendStringInfoCharMacro(out, '}');
				first = false;
				break;
			default:
				elog(ERROR, "unknown jsonb iterator token type");
		}
		use_indent = indent;
		last_was_key = redo_switch;
	}

	Assert(level == 0);

	return out->data;
}
Exemplo n.º 5
0
static char *add_desc(char *base, size_t *len, size_t *max,
		      unsigned int indent, unsigned int width,
		      const struct opt_table *opt)
{
	size_t off, prefix, l;
	const char *p;
	bool same_line = false;

	base = add_str(base, len, max, opt->names);
	off = strlen(opt->names);
	if (opt->type == OPT_HASARG
	    && !strchr(opt->names, ' ')
	    && !strchr(opt->names, '=')) {
		base = add_str(base, len, max, " <arg>");
		off += strlen(" <arg>");
	}

	/* Do we start description on next line? */
	if (off + 2 > indent) {
		base = add_str(base, len, max, "\n");
		off = 0;
	} else {
		base = add_indent(base, len, max, indent - off);
		off = indent;
		same_line = true;
	}

	/* Indent description. */
	p = opt->desc;
	while ((l = consume_words(p, width - indent, &prefix)) != 0) {
		if (!same_line)
			base = add_indent(base, len, max, indent);
		p += prefix;
		base = add_str_len(base, len, max, p, l);
		base = add_str(base, len, max, "\n");
		off = indent + l;
		p += l;
		same_line = false;
	}

	/* Empty description?  Make it match normal case. */
	if (same_line)
		base = add_str(base, len, max, "\n");

	if (opt->show) {
		char buf[OPT_SHOW_LEN + sizeof("...")];
		strcpy(buf + OPT_SHOW_LEN, "...");
		opt->show(buf, opt->u.arg);

		/* If it doesn't fit on this line, indent. */
		if (off + strlen(" (default: ") + strlen(buf) + strlen(")")
		    > width) {
			base = add_indent(base, len, max, indent);
		} else {
			/* Remove \n. */
			(*len)--;
		}

		base = add_str(base, len, max, " (default: ");
		base = add_str(base, len, max, buf);
		base = add_str(base, len, max, ")\n");
	}
	return base;
}