aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/libfyaml/src/lib/fy-walk.h
blob: bc200f66ebeb415338adc14e4a653d445b67cca7 (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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
/*
 * fy-walk.h - walker  internal header file
 *
 * Copyright (c) 2021 Pantelis Antoniou <pantelis.antoniou@konsulko.com>
 *
 * SPDX-License-Identifier: MIT
 */
#ifndef FY_WALK_H
#define FY_WALK_H

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

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

#include <libfyaml.h>

#include "fy-ctype.h"
#include "fy-utf8.h"
#include "fy-list.h"
#include "fy-typelist.h"
#include "fy-types.h"
#include "fy-diag.h"
#include "fy-dump.h"
#include "fy-docstate.h"
#include "fy-accel.h"
#include "fy-token.h"

struct fy_document;

enum fy_walk_result_type {
	fwrt_none,
	fwrt_node_ref,
	fwrt_number,
	fwrt_string,
	fwrt_doc,
	fwrt_refs,
};

#define FWRT_COUNT (fwrt_refs + 1)
extern const char *fy_walk_result_type_txt[FWRT_COUNT];

struct fy_path_exec;

FY_TYPE_FWD_DECL_LIST(walk_result);
struct fy_walk_result {
	struct fy_list_head node;
	struct fy_path_exec *fypx;
	enum fy_walk_result_type type;
	union {
		struct fy_node *fyn;
		double number;
		char *string;
		struct fy_walk_result_list refs;
		struct fy_document *fyd;
	};
};
FY_TYPE_DECL_LIST(walk_result);

struct fy_walk_result *fy_walk_result_alloc_rl(struct fy_walk_result_list *fwrl);
void fy_walk_result_free_rl(struct fy_walk_result_list *fwrl, struct fy_walk_result *fwr);
void fy_walk_result_list_free_rl(struct fy_walk_result_list *fwrl, struct fy_walk_result_list *results);

void fy_walk_result_free(struct fy_walk_result *fwr);

struct fy_walk_result *fy_walk_result_vcreate_rl(struct fy_walk_result_list *fwrl, enum fy_walk_result_type type, va_list ap);
struct fy_walk_result *fy_walk_result_create_rl(struct fy_walk_result_list *fwrl, enum fy_walk_result_type type, ...);

static inline struct fy_walk_result *
fy_walk_result_iter_start(struct fy_walk_result *fwr)
{
	struct fy_walk_result *fwri;

	if (!fwr)
		return NULL;
	if (fwr->type != fwrt_refs)
		return fwr;
	fwri = fy_walk_result_list_head(&fwr->refs);
	if (!fwri)
		return NULL;
	return fwri;
}

static inline struct fy_walk_result *
fy_walk_result_iter_next(struct fy_walk_result *fwr, struct fy_walk_result *fwri)
{
	if (!fwr || !fwri || fwr->type != fwrt_refs)
		return NULL;
	fwri = fy_walk_result_next(&fwr->refs, fwri);
	if (!fwri)
		return NULL;
	return fwri;
}

struct fy_node *
fy_walk_result_node_iterate(struct fy_walk_result *fwr, void **prevp);

enum fy_path_expr_type {
	fpet_none,
	/* ypath */
	fpet_root,		/* /^ or / at the beginning of the expr */
	fpet_this,		/* /. */
	fpet_parent,		/* /.. */
	fpet_every_child,	// /* every immediate child
	fpet_every_child_r,	// /** every recursive child
	fpet_filter_collection,	/* match only collection (at the end only) */
	fpet_filter_scalar,	/* match only scalars (leaves) */
	fpet_filter_sequence,	/* match only sequences */
	fpet_filter_mapping,	/* match only mappings */
	fpet_filter_unique,	/* removes duplicates */
	fpet_seq_index,
	fpet_map_key,		/* complex map key (quoted, flow seq or map) */
	fpet_seq_slice,
	fpet_alias,

	fpet_multi,		/* merge results of children */
	fpet_chain,		/* children move in sequence */
	fpet_logical_or,	/* first non null result set */
	fpet_logical_and,	/* the last non null result set */

	fpet_eq,		/* equal expression */
	fpet_neq,		/* not equal */
	fpet_lt,		/* less than */
	fpet_gt,		/* greater than */
	fpet_lte,		/* less or equal than */
	fpet_gte,		/* greater or equal than */

	fpet_scalar,		/* scalar */

	fpet_plus,		/* add */
	fpet_minus,		/* subtract */
	fpet_mult,		/* multiply */
	fpet_div,		/* divide */

	fpet_lparen,		/* left paren (they do not appear in final expression) */
	fpet_rparen,		/* right parent */
	fpet_method,		/* method (or parentheses) */

	fpet_scalar_expr,	/* non-eval phase scalar expression  */
	fpet_path_expr,		/* non-eval phase path expression */
	fpet_arg_separator,	/* argument separator (comma in scalar mode) */
};

#define FPET_COUNT (fpet_arg_separator + 1)

extern const char *path_expr_type_txt[FPET_COUNT];

static inline bool fy_path_expr_type_is_valid(enum fy_path_expr_type type)
{
	return type >= fpet_root && type < FPET_COUNT;
}

static inline bool fy_path_expr_type_is_single_result(enum fy_path_expr_type type)
{
	return type == fpet_root ||
	       type == fpet_this ||
	       type == fpet_parent ||
	       type == fpet_map_key ||
	       type == fpet_seq_index ||
	       type == fpet_alias ||
	       type == fpet_filter_collection ||
	       type == fpet_filter_scalar ||
	       type == fpet_filter_sequence ||
	       type == fpet_filter_mapping;
}

static inline bool fy_path_expr_type_is_parent(enum fy_path_expr_type type)
{
	return type == fpet_multi ||
	       type == fpet_chain ||
	       type == fpet_logical_or ||
	       type == fpet_logical_and ||
	       type == fpet_eq ||
	       type == fpet_method ||
	       type == fpet_scalar_expr ||
	       type == fpet_path_expr;
}

static inline bool fy_path_expr_type_is_mergeable(enum fy_path_expr_type type)
{
	return type == fpet_multi ||
	       type == fpet_chain ||
	       type == fpet_logical_or ||
	       type == fpet_logical_and;
}

/* type handles refs by itself */
static inline bool fy_path_expr_type_handles_refs(enum fy_path_expr_type type)
{
	return type == fpet_filter_unique ||
	       type == fpet_method;
}

static inline bool fy_path_expr_type_is_parent_lhs_rhs(enum fy_path_expr_type type)
{
	return type == fpet_eq ||
	       type == fpet_neq ||
	       type == fpet_lt ||
	       type == fpet_gt ||
	       type == fpet_lte ||
	       type == fpet_gte ||

	       type == fpet_plus ||
	       type == fpet_minus ||
	       type == fpet_mult ||
	       type == fpet_div;
}

static inline bool
fy_path_expr_type_is_conditional(enum fy_path_expr_type type)
{
	return type == fpet_eq ||
	       type == fpet_neq ||
	       type == fpet_lt ||
	       type == fpet_gt ||
	       type == fpet_lte ||
	       type == fpet_gte;
}

static inline bool
fy_path_expr_type_is_arithmetic(enum fy_path_expr_type type)
{
	return type == fpet_plus ||
	       type == fpet_minus ||
	       type == fpet_mult ||
	       type == fpet_div;
}

static inline bool
fy_path_expr_type_is_lparen(enum fy_path_expr_type type)
{
	return type == fpet_lparen /* ||
	       type == fpet_method */ ;
}

enum fy_expr_mode {
	fyem_none,	/* invalid mode */
	fyem_path,	/* expression is path */
	fyem_scalar,	/* expression is scalar */
};

#define FYEM_COUNT (fyem_scalar + 1)

extern const char *fy_expr_mode_txt[FYEM_COUNT];

struct fy_path_expr;

struct fy_method {
	const char *name;
	size_t len;
	enum fy_expr_mode mode;
	unsigned int nargs;
	struct fy_walk_result *(*exec)(const struct fy_method *fym,
		struct fy_path_exec *fypx, int level,
		struct fy_path_expr *expr,
		struct fy_walk_result *input,
		struct fy_walk_result **args, int nargs);
};

FY_TYPE_FWD_DECL_LIST(path_expr);
struct fy_path_expr {
	struct fy_list_head node;
	struct fy_path_expr *parent;
	enum fy_path_expr_type type;
	struct fy_token *fyt;
	struct fy_path_expr_list children;
	enum fy_expr_mode expr_mode;	/* for parens */
	const struct fy_method *fym;
};
FY_TYPE_DECL_LIST(path_expr);

static inline struct fy_path_expr *
fy_path_expr_lhs(struct fy_path_expr *expr)
{
	if (!expr || !fy_path_expr_type_is_parent_lhs_rhs(expr->type))
		return NULL;
	return fy_path_expr_list_head(&expr->children);
}

static inline struct fy_path_expr *
fy_path_expr_rhs(struct fy_path_expr *expr)
{
	if (!expr || !fy_path_expr_type_is_parent_lhs_rhs(expr->type))
		return NULL;
	return fy_path_expr_list_tail(&expr->children);
}

const struct fy_mark *fy_path_expr_start_mark(struct fy_path_expr *expr);
const struct fy_mark *fy_path_expr_end_mark(struct fy_path_expr *expr);

struct fy_expr_stack {
	unsigned int top;
	unsigned int alloc;
	struct fy_path_expr **items;
	struct fy_path_expr *items_static[32];
};

void fy_expr_stack_setup(struct fy_expr_stack *stack);
void fy_expr_stack_cleanup(struct fy_expr_stack *stack);
void fy_expr_stack_dump(struct fy_diag *diag, struct fy_expr_stack *stack);
int fy_expr_stack_push(struct fy_expr_stack *stack, struct fy_path_expr *expr);
struct fy_path_expr *fy_expr_stack_peek_at(struct fy_expr_stack *stack, unsigned int pos);
struct fy_path_expr *fy_expr_stack_peek(struct fy_expr_stack *stack);
struct fy_path_expr *fy_expr_stack_pop(struct fy_expr_stack *stack);

struct fy_path_parser {
	struct fy_path_parse_cfg cfg;
	struct fy_reader reader;
	struct fy_token_list queued_tokens;
	enum fy_token_type last_queued_token_type;
	bool stream_start_produced;
	bool stream_end_produced;
	bool stream_error;
	int token_activity_counter;

	struct fy_input *fyi;
	struct fy_expr_stack operators;
	struct fy_expr_stack operands;

	/* to avoid allocating */
	struct fy_path_expr_list expr_recycle;
	bool suppress_recycling;

	enum fy_expr_mode expr_mode;
	int paren_nest_level;

};

struct fy_path_expr *fy_path_expr_alloc(void);
/* fy_path_expr_free is declared in libfyaml.h */
// void fy_path_expr_free(struct fy_path_expr *expr);

void fy_path_parser_setup(struct fy_path_parser *fypp, const struct fy_path_parse_cfg *pcfg);
void fy_path_parser_cleanup(struct fy_path_parser *fypp);
int fy_path_parser_open(struct fy_path_parser *fypp,
			struct fy_input *fyi, const struct fy_reader_input_cfg *icfg);
void fy_path_parser_close(struct fy_path_parser *fypp);

struct fy_token *fy_path_scan(struct fy_path_parser *fypp);

struct fy_path_expr *fy_path_parse_expression(struct fy_path_parser *fypp);

void fy_path_expr_dump(struct fy_path_expr *expr, struct fy_diag *diag, enum fy_error_type errlevel, int level, const char *banner);

struct fy_path_exec {
	struct fy_path_exec_cfg cfg;
	struct fy_node *fyn_start;
	struct fy_walk_result *result;
	struct fy_walk_result_list *fwr_recycle;
	int refs;
	bool supress_recycling;
};

struct fy_path_exec *fy_path_exec_create(const struct fy_path_exec_cfg *xcfg);
struct fy_path_exec *fy_path_exec_create_on_document(struct fy_document *fyd);
void fy_path_exec_destroy(struct fy_path_exec *fypx);
void fy_path_exec_cleanup(struct fy_path_exec *fypx);

static inline struct fy_path_exec *
fy_path_exec_ref(struct fy_path_exec *fypx)
{
	/* take care of overflow */
	if (!fypx)
		return NULL;
	assert(fypx->refs + 1 > 0);
	fypx->refs++;

	return fypx;
}

static inline void
fy_path_exec_unref(struct fy_path_exec *fypx)
{
	if (!fypx)
		return;

	assert(fypx->refs > 0);

	if (--fypx->refs == 0)
		fy_path_exec_destroy(fypx);
}

struct fy_walk_result *
fy_path_expr_execute(struct fy_path_exec *fypx, int level, struct fy_path_expr *expr,
		     struct fy_walk_result *input, enum fy_path_expr_type ptype);

static inline struct fy_walk_result_list *
fy_path_exec_walk_result_rl(struct fy_path_exec *fypx)
{
	return fypx && !fypx->supress_recycling ? fypx->fwr_recycle : NULL;
}

static inline void
fy_path_exec_set_result_recycle_list(struct fy_path_exec *fypx,
				     struct fy_walk_result_list *fwrl)
{
	if (!fypx)
		return;
	fypx->fwr_recycle = fwrl;
}

struct fy_walk_result *
fy_path_exec_walk_result_create(struct fy_path_exec *fypx, enum fy_walk_result_type type, ...);

void
fy_path_exec_walk_result_free(struct fy_path_exec *fypx, struct fy_walk_result *fwr);

struct fy_path_expr_document_data {
	struct fy_path_parser *fypp;
	struct fy_walk_result_list fwr_recycle;
};

struct fy_path_expr_node_data {
	struct fy_input *fyi;
	struct fy_path_expr *expr;
	struct fy_node *fyn_target;
	int traversals;
};

int fy_document_setup_path_expr_data(struct fy_document *fyd);
void fy_document_cleanup_path_expr_data(struct fy_document *fyd);
int fy_node_setup_path_expr_data(struct fy_node *fyn);
void fy_node_cleanup_path_expr_data(struct fy_node *fyn);

struct fy_walk_result *
fy_node_alias_resolve_by_ypath_result(struct fy_node *fyn);
struct fy_node *fy_node_alias_resolve_by_ypath(struct fy_node *fyn);

struct fy_walk_result *
fy_node_by_ypath_result(struct fy_node *fyn, const char *path, size_t len);
struct fy_node *fy_node_by_ypath(struct fy_node *fyn, const char *path, size_t len);

#endif