aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/libfyaml/src/lib/fy-emit.h
blob: 3bbd8b5f1c7b12bb468b1a7bdde4f658e73e17e7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
 * fy-emit.h - internal YAML emitter header
 *
 * Copyright (c) 2019 Pantelis Antoniou <pantelis.antoniou@konsulko.com>
 *
 * SPDX-License-Identifier: MIT
 */
#ifndef FY_EMIT_H
#define FY_EMIT_H

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>

#include <libfyaml.h>

#include "fy-utf8.h"
#include "fy-event.h"
#include "fy-emit-accum.h"

#define FYEF_WHITESPACE			0x0001
#define FYEF_INDENTATION		0x0002
#define FYEF_OPEN_ENDED			0x0004
#define FYEF_HAD_DOCUMENT_START		0x0008
#define FYEF_HAD_DOCUMENT_END		0x0010
#define FYEF_HAD_DOCUMENT_OUTPUT	0x0020

struct fy_document;
struct fy_emitter;
struct fy_document_state;

enum fy_emitter_state {
	FYES_NONE,		/* when not using the raw emitter interface */
	FYES_STREAM_START,
	FYES_FIRST_DOCUMENT_START,
	FYES_DOCUMENT_START,
	FYES_DOCUMENT_CONTENT,
	FYES_DOCUMENT_END,
	FYES_SEQUENCE_FIRST_ITEM,
	FYES_SEQUENCE_ITEM,
	FYES_MAPPING_FIRST_KEY,
	FYES_MAPPING_KEY,
	FYES_MAPPING_SIMPLE_VALUE,
	FYES_MAPPING_VALUE,
	FYES_END,
};

struct fy_emit_save_ctx {
	bool flow_token : 1;
	bool flow : 1;
	bool empty : 1;
	int old_indent;
	int flags;
	int indent;
	struct fy_token *fyt_last_key;
	struct fy_token *fyt_last_value;
	int s_flags;
	int s_indent;
};

/* internal flags */
#define DDNF_ROOT		0x0001
#define DDNF_SEQ		0x0002
#define DDNF_MAP		0x0004
#define DDNF_SIMPLE		0x0008
#define DDNF_FLOW		0x0010
#define DDNF_INDENTLESS		0x0020
#define DDNF_SIMPLE_SCALAR_KEY	0x0040

struct fy_emitter {
	int line;
	int column;
	int flow_level;
	unsigned int flags;
	bool output_error : 1;
	bool source_json : 1;		/* the source was json */
	bool force_json : 1;		/* force JSON mode unconditionally */
	bool suppress_recycling_force : 1;
	bool suppress_recycling : 1;

	/* current document */
	struct fy_emitter_cfg cfg;	/* yeah, it isn't worth just to save a few bytes */
	struct fy_document *fyd;
	struct fy_document_state *fyds;	/* fyd->fyds when fyd != NULL */
	struct fy_emit_accum ea;
	char ea_inplace_buf[256];	/* the in place accumulator buffer before allocating */
	struct fy_diag *diag;

	/* streaming event mode */
	enum fy_emitter_state state;
	enum fy_emitter_state *state_stack;
	unsigned int state_stack_alloc;
	unsigned int state_stack_top;
	enum fy_emitter_state state_stack_inplace[64];
	struct fy_eventp_list queued_events;
	int s_indent;
	int s_flags;
	struct fy_emit_save_ctx s_sc;
	struct fy_emit_save_ctx *sc_stack;
	unsigned int sc_stack_alloc;
	unsigned int sc_stack_top;
	struct fy_emit_save_ctx sc_stack_inplace[16];

	/* recycled */
	struct fy_eventp_list recycled_eventp;
	struct fy_token_list recycled_token;

	struct fy_eventp_list *recycled_eventp_list;	/* NULL when suppressing */
	struct fy_token_list *recycled_token_list;	/* NULL when suppressing */

	/* for special needs */
	void (*finalizer)(struct fy_emitter *emit);
};

int fy_emit_setup(struct fy_emitter *emit, const struct fy_emitter_cfg *cfg);
void fy_emit_cleanup(struct fy_emitter *emit);

void fy_emit_write(struct fy_emitter *emit, enum fy_emitter_write_type type, const char *str, int len);

static inline bool fy_emit_whitespace(struct fy_emitter *emit)
{
	return !!(emit->flags & FYEF_WHITESPACE);
}

static inline bool fy_emit_indentation(struct fy_emitter *emit)
{
	return !!(emit->flags & FYEF_INDENTATION);
}

static inline bool fy_emit_open_ended(struct fy_emitter *emit)
{
	return !!(emit->flags & FYEF_OPEN_ENDED);
}

static inline void
fy_emit_output_accum(struct fy_emitter *emit, enum fy_emitter_write_type type, struct fy_emit_accum *ea)
{
	const char *text;
	size_t len;

	text = fy_emit_accum_get(ea, &len);
	if (text && len > 0)
		fy_emit_write(emit, type, text, len);
	fy_emit_accum_reset(ea);
}

#endif