Blame yaml-filter/yaml-path.c

Packit 517ee8
#include <stdlib.h>
Packit 517ee8
#include <stdbool.h>
Packit 517ee8
#include <string.h>
Packit 517ee8
#include <sys/queue.h>
Packit 517ee8
#include <assert.h>
Packit 517ee8
Packit 517ee8
#include <yaml.h>
Packit 517ee8
Packit 517ee8
#include "yaml-path.h"
Packit 517ee8
Packit 517ee8
Packit 517ee8
#define YAML_PATH_MAX_SECTION_LEN 1024
Packit 517ee8
#define YAML_PATH_MAX_SECTIONS    255
Packit 517ee8
#define YAML_PATH_MAX_LEN         YAML_PATH_MAX_SECTION_LEN * YAML_PATH_MAX_SECTIONS
Packit 517ee8
Packit 517ee8
Packit 517ee8
typedef enum yaml_path_section_type {
Packit 517ee8
	YAML_PATH_SECTION_ROOT,
Packit 517ee8
	YAML_PATH_SECTION_ANCHOR,
Packit 517ee8
	YAML_PATH_SECTION_KEY,
Packit 517ee8
	YAML_PATH_SECTION_INDEX,
Packit 517ee8
	YAML_PATH_SECTION_SLICE,
Packit 517ee8
} yaml_path_section_type_t;
Packit 517ee8
Packit 517ee8
typedef struct yaml_path_section {
Packit 517ee8
	yaml_path_section_type_t type;
Packit 517ee8
	int level;
Packit 517ee8
	union {
Packit 517ee8
		const char *key;
Packit 517ee8
		const char *anchor;
Packit 517ee8
		int index;
Packit 517ee8
		struct {int start, end, stride;} slice;
Packit 517ee8
	} data;
Packit 517ee8
	TAILQ_ENTRY(yaml_path_section) entries;
Packit 517ee8
Packit 517ee8
	yaml_node_type_t node_type;
Packit 517ee8
	int counter;
Packit 517ee8
	bool valid;
Packit 517ee8
	bool next_valid;
Packit 517ee8
} yaml_path_section_t;
Packit 517ee8
Packit 517ee8
typedef TAILQ_HEAD(path_section_list, yaml_path_section) path_section_list_t;
Packit 517ee8
Packit 517ee8
typedef struct yaml_path {
Packit 517ee8
	path_section_list_t sections_list;
Packit 517ee8
	size_t sections_count;
Packit 517ee8
	size_t sequence_level;
Packit 517ee8
Packit 517ee8
	size_t current_level;
Packit 517ee8
	size_t start_level;
Packit 517ee8
Packit 517ee8
	yaml_path_error_t error;
Packit 517ee8
} yaml_path_t;
Packit 517ee8
Packit 517ee8
Packit 517ee8
static void
Packit 517ee8
yaml_path_error_set (yaml_path_t *path, yaml_path_error_type_t error_type, const char *message, size_t pos)
Packit 517ee8
{
Packit 517ee8
	assert(path != NULL);
Packit 517ee8
	path->error.type = error_type;
Packit 517ee8
	path->error.message = message;
Packit 517ee8
	path->error.pos = pos;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static void
Packit 517ee8
yaml_path_sections_remove (yaml_path_t *path)
Packit 517ee8
{
Packit 517ee8
	assert(path != NULL);
Packit 517ee8
	while (!TAILQ_EMPTY(&path->sections_list)) {
Packit 517ee8
		yaml_path_section_t *el = TAILQ_FIRST(&path->sections_list);
Packit 517ee8
		TAILQ_REMOVE(&path->sections_list, el, entries);
Packit 517ee8
		path->sections_count--;
Packit 517ee8
		switch (el->type) {
Packit 517ee8
		case YAML_PATH_SECTION_KEY:
Packit 517ee8
			free((void *)el->data.key);
Packit 517ee8
			break;
Packit 517ee8
		case YAML_PATH_SECTION_ANCHOR:
Packit 517ee8
			free((void *)el->data.anchor);
Packit 517ee8
			break;
Packit 517ee8
		case YAML_PATH_SECTION_SLICE:
Packit 517ee8
			if (path->sequence_level == el->level)
Packit 517ee8
				path->sequence_level = 0;
Packit 517ee8
			break;
Packit 517ee8
		default:
Packit 517ee8
			break;
Packit 517ee8
		}
Packit 517ee8
		free(el);
Packit 517ee8
	}
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static yaml_path_section_t*
Packit 517ee8
yaml_path_section_create (yaml_path_t *path, yaml_path_section_type_t section_type)
Packit 517ee8
{
Packit 517ee8
	yaml_path_section_t *el = malloc(sizeof(*el));
Packit 517ee8
	assert(el != NULL);
Packit 517ee8
	memset(el, 0, sizeof(*el));
Packit 517ee8
	path->sections_count++;
Packit 517ee8
	el->level = path->sections_count;
Packit 517ee8
	el->type = section_type;
Packit 517ee8
	el->node_type = YAML_SCALAR_NODE;
Packit 517ee8
	TAILQ_INSERT_TAIL(&path->sections_list, el, entries);
Packit 517ee8
	if (el->type == YAML_PATH_SECTION_SLICE && !path->sequence_level) {
Packit 517ee8
		path->sequence_level = el->level;
Packit 517ee8
	}
Packit 517ee8
	return el;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static size_t
Packit 517ee8
yaml_path_section_snprint (yaml_path_section_t *section, char *s, size_t max_len)
Packit 517ee8
{
Packit 517ee8
	assert(section != NULL);
Packit 517ee8
	if (s == NULL)
Packit 517ee8
		return -1;
Packit 517ee8
	size_t len = 0;
Packit 517ee8
	switch (section->type) {
Packit 517ee8
	case YAML_PATH_SECTION_ROOT:
Packit 517ee8
		len = snprintf(s, max_len, "$");
Packit 517ee8
		break;
Packit 517ee8
	case YAML_PATH_SECTION_KEY:
Packit 517ee8
		len = snprintf(s, max_len, ".%s", section->data.key);
Packit 517ee8
		break;
Packit 517ee8
	case YAML_PATH_SECTION_ANCHOR:
Packit 517ee8
		len = snprintf(s, max_len, "&%s", section->data.anchor);
Packit 517ee8
		break;
Packit 517ee8
	case YAML_PATH_SECTION_INDEX:
Packit 517ee8
		len = snprintf(s, max_len, "[%d]", section->data.index);
Packit 517ee8
		break;
Packit 517ee8
	case YAML_PATH_SECTION_SLICE:
Packit 517ee8
		len = snprintf(s, max_len, "[%d:%d:%d]", section->data.slice.start, section->data.slice.end, section->data.slice.stride);
Packit 517ee8
		break;
Packit 517ee8
	default:
Packit 517ee8
		len = snprintf(s, max_len, "");
Packit 517ee8
		break;
Packit 517ee8
	}
Packit 517ee8
	return len;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static void
Packit 517ee8
_parse (yaml_path_t *path, char *s_path) {
Packit 517ee8
	char *sp = s_path;
Packit 517ee8
	char *spe = NULL;
Packit 517ee8
Packit 517ee8
	assert(path != NULL);
Packit 517ee8
Packit 517ee8
	if (s_path == NULL || !s_path[0]) {
Packit 517ee8
		yaml_path_error_set(path, YAML_PATH_ERROR_PARSE, "Path is empty", 0);
Packit 517ee8
		return;
Packit 517ee8
	}
Packit 517ee8
Packit 517ee8
	while (*sp != '\0') {
Packit 517ee8
		switch (*sp) {
Packit 517ee8
		case '.':
Packit 517ee8
		case '[':
Packit 517ee8
			if (path->sections_count == 0) {
Packit 517ee8
				yaml_path_section_create(path, YAML_PATH_SECTION_ROOT);
Packit 517ee8
			}
Packit 517ee8
			if (*sp == '.') {
Packit 517ee8
				// Key
Packit 517ee8
				spe = sp + 1;
Packit 517ee8
				while (*spe != '.' && *spe != '[' && *spe != '\0')
Packit 517ee8
					spe++;
Packit 517ee8
				if (spe == sp+1) {
Packit 517ee8
					yaml_path_error_set(path, YAML_PATH_ERROR_PARSE, "Segment key is missing", sp - s_path);
Packit 517ee8
					goto error;
Packit 517ee8
				}
Packit 517ee8
				yaml_path_section_t *sec = yaml_path_section_create(path, YAML_PATH_SECTION_KEY);
Packit 517ee8
				sec->data.key = strndup(sp + 1, spe-sp - 1);
Packit 517ee8
				sp = spe-1;
Packit 517ee8
			} else if (*sp == '[') {
Packit 517ee8
				spe = sp+1;
Packit 517ee8
				if (*spe == '\'') {
Packit 517ee8
					// Key
Packit 517ee8
					sp = spe;
Packit 517ee8
					spe++;
Packit 517ee8
					while (*spe != '\'' && *spe != '\0')
Packit 517ee8
						spe++;
Packit 517ee8
					if (spe == sp+1) {
Packit 517ee8
						yaml_path_error_set(path, YAML_PATH_ERROR_PARSE, "Segment key is missing", sp - s_path);
Packit 517ee8
						goto error;
Packit 517ee8
					}
Packit 517ee8
					if (*spe == '\0') {
Packit 517ee8
						yaml_path_error_set(path, YAML_PATH_ERROR_PARSE, "Segment key is invalid (unxepected end of string, missing ''')", sp - s_path);
Packit 517ee8
						goto error;
Packit 517ee8
					}
Packit 517ee8
					spe++;
Packit 517ee8
					if (*spe == '\0') {
Packit 517ee8
						yaml_path_error_set(path, YAML_PATH_ERROR_PARSE, "Segment key is invalid (unxepected end of string, missing ']')", sp - s_path);
Packit 517ee8
						goto error;
Packit 517ee8
					}
Packit 517ee8
					if (*spe != ']') {
Packit 517ee8
						yaml_path_error_set(path, YAML_PATH_ERROR_PARSE, "Segment key is invalid (invalid character)", spe - s_path);
Packit 517ee8
						goto error;
Packit 517ee8
					}
Packit 517ee8
					yaml_path_section_t *sec = yaml_path_section_create(path, YAML_PATH_SECTION_KEY);
Packit 517ee8
					sec->data.key = strndup(sp + 1, spe-sp - 2);
Packit 517ee8
					sp = spe;
Packit 517ee8
				} else {
Packit 517ee8
					// Index or Slice
Packit 517ee8
					int idx = strtol(spe, &spe, 10);
Packit 517ee8
					if (*spe == ']') {
Packit 517ee8
						// Index
Packit 517ee8
						yaml_path_section_t *sec = yaml_path_section_create(path, YAML_PATH_SECTION_INDEX);
Packit 517ee8
						sec->data.index = idx;
Packit 517ee8
						sp = spe;
Packit 517ee8
					} else if (*spe == ':') {
Packit 517ee8
						// Slice
Packit 517ee8
						int idx_start = idx;
Packit 517ee8
						sp = spe++;
Packit 517ee8
						idx = strtol(spe, &spe, 10);
Packit 517ee8
						if (*spe == ':') {
Packit 517ee8
							int idx_end = (spe == sp+1 ? __INT_MAX__ : idx);
Packit 517ee8
							sp = spe++;
Packit 517ee8
							idx = strtol(spe, &spe, 10);
Packit 517ee8
							if (*spe == ']' && (idx > 0 || spe == sp+1)) {
Packit 517ee8
								yaml_path_section_t *sec = yaml_path_section_create(path, YAML_PATH_SECTION_SLICE);
Packit 517ee8
								sec->data.slice.start = idx_start;
Packit 517ee8
								sec->data.slice.end = idx_end;
Packit 517ee8
								sec->data.slice.stride = idx > 0 ? idx : 1;
Packit 517ee8
								sp = spe;
Packit 517ee8
							} else if (*spe == ']' && idx <= 0) {
Packit 517ee8
								yaml_path_error_set(path, YAML_PATH_ERROR_PARSE, "Segment slice stride can not be less than 1", spe - s_path - 1);
Packit 517ee8
								goto error;
Packit 517ee8
							} else {
Packit 517ee8
								yaml_path_error_set(path, YAML_PATH_ERROR_PARSE, "Segment slice stride is invalid (invalid character)", spe - s_path);
Packit 517ee8
								goto error;
Packit 517ee8
							}
Packit 517ee8
						} else if (*spe == ']') {
Packit 517ee8
							yaml_path_section_t *sec = yaml_path_section_create(path, YAML_PATH_SECTION_SLICE);
Packit 517ee8
							sec->data.slice.start = idx_start;
Packit 517ee8
							sec->data.slice.end = (spe == sp+1 ? __INT_MAX__ : idx);
Packit 517ee8
							sec->data.slice.stride = 1;
Packit 517ee8
							sp = spe;
Packit 517ee8
						} else {
Packit 517ee8
							yaml_path_error_set(path, YAML_PATH_ERROR_PARSE, "Segment slice end index is invalid (invalid character)", spe - s_path);
Packit 517ee8
							goto error;
Packit 517ee8
						}
Packit 517ee8
					} else if (*spe == '\0') {
Packit 517ee8
						yaml_path_error_set(path, YAML_PATH_ERROR_PARSE, "Segment index is invalid (unxepected end of string, missing ']')", spe - s_path);
Packit 517ee8
						goto error;
Packit 517ee8
					} else {
Packit 517ee8
						yaml_path_error_set(path, YAML_PATH_ERROR_PARSE, "Segment index is invalid (invalid character)", spe - s_path);
Packit 517ee8
						goto error;
Packit 517ee8
					}
Packit 517ee8
				}
Packit 517ee8
			}
Packit 517ee8
			break;
Packit 517ee8
		default:
Packit 517ee8
			if (path->sections_count == 0) {
Packit 517ee8
				spe = sp + 1;
Packit 517ee8
				if (*sp == '$' && (*spe == '.' || *spe == '[' || *spe == '\0')) {
Packit 517ee8
					yaml_path_section_t *sec = yaml_path_section_create(path, YAML_PATH_SECTION_ROOT);
Packit 517ee8
				} else if (*sp == '&') {
Packit 517ee8
					// Anchor
Packit 517ee8
					sp++;
Packit 517ee8
					while (*spe != '.' && *spe != '[' && *spe != '\0')
Packit 517ee8
						spe++;
Packit 517ee8
					yaml_path_section_t *sec = yaml_path_section_create(path, YAML_PATH_SECTION_ANCHOR);
Packit 517ee8
					sec->data.anchor = strndup(sp, spe-sp);
Packit 517ee8
				} else {
Packit 517ee8
					// Key
Packit 517ee8
					while (*spe != '.' && *spe != '[' && *spe != '\0')
Packit 517ee8
						spe++;
Packit 517ee8
					yaml_path_section_t *sec = yaml_path_section_create(path, YAML_PATH_SECTION_ROOT);
Packit 517ee8
					sec = yaml_path_section_create(path, YAML_PATH_SECTION_KEY);
Packit 517ee8
					sec->data.key = strndup(sp, spe-sp);
Packit 517ee8
				}
Packit 517ee8
				sp = spe-1;
Packit 517ee8
			}
Packit 517ee8
			break;
Packit 517ee8
		}
Packit 517ee8
		sp++;
Packit 517ee8
	}
Packit 517ee8
Packit 517ee8
	if (path->sections_count == 0) {
Packit 517ee8
		yaml_path_error_set(path, YAML_PATH_ERROR_PARSE, "Invalid path segments", 0);
Packit 517ee8
	}
Packit 517ee8
Packit 517ee8
	return;
Packit 517ee8
Packit 517ee8
error:
Packit 517ee8
	yaml_path_sections_remove(path);
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static yaml_path_section_t*
Packit 517ee8
yaml_path_section_get_at_level (yaml_path_t *path, size_t level)
Packit 517ee8
{
Packit 517ee8
	assert(path != NULL);
Packit 517ee8
	yaml_path_section_t *el;
Packit 517ee8
	TAILQ_FOREACH(el, &path->sections_list, entries) {
Packit 517ee8
		if (el->level == level)
Packit 517ee8
			return el;
Packit 517ee8
	}
Packit 517ee8
	return NULL;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static yaml_path_section_t*
Packit 517ee8
yaml_path_section_get_first (yaml_path_t *path)
Packit 517ee8
{
Packit 517ee8
	assert(path != NULL);
Packit 517ee8
	return yaml_path_section_get_at_level(path, 1);
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static yaml_path_section_t*
Packit 517ee8
yaml_path_section_get_current (yaml_path_t *path)
Packit 517ee8
{
Packit 517ee8
	assert(path != NULL);
Packit 517ee8
	if (!path->start_level)
Packit 517ee8
		return NULL;
Packit 517ee8
	return yaml_path_section_get_at_level(path, path->current_level - path->start_level + 1);
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static bool
Packit 517ee8
yaml_path_sections_prev_are_valid (yaml_path_t *path)
Packit 517ee8
{
Packit 517ee8
	assert(path != NULL);
Packit 517ee8
	int valid = true;
Packit 517ee8
	yaml_path_section_t *el;
Packit 517ee8
	TAILQ_FOREACH(el, &path->sections_list, entries) {
Packit 517ee8
		if (el->level < path->current_level - path->start_level + 1)
Packit 517ee8
			valid = el->valid && valid;
Packit 517ee8
	}
Packit 517ee8
	return valid;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static bool
Packit 517ee8
yaml_path_section_current_is_last (yaml_path_t *path)
Packit 517ee8
{
Packit 517ee8
	assert(path != NULL);
Packit 517ee8
	yaml_path_section_t *sec = yaml_path_section_get_current(path);
Packit 517ee8
	if (sec == NULL)
Packit 517ee8
		return false;
Packit 517ee8
	return sec->level == path->sections_count;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static bool
Packit 517ee8
yaml_path_section_current_is_mandatory_sequence (yaml_path_t *path)
Packit 517ee8
{
Packit 517ee8
	assert(path != NULL);
Packit 517ee8
	yaml_path_section_t *sec = yaml_path_section_get_current(path);
Packit 517ee8
	if (sec == NULL)
Packit 517ee8
		return false;
Packit 517ee8
	return (sec->type == YAML_PATH_SECTION_SLICE && sec->level == path->sequence_level);
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static bool
Packit 517ee8
yaml_path_is_valid (yaml_path_t *path)
Packit 517ee8
{
Packit 517ee8
	assert(path != NULL);
Packit 517ee8
	bool valid = true;
Packit 517ee8
	yaml_path_section_t *el;
Packit 517ee8
	TAILQ_FOREACH(el, &path->sections_list, entries) {
Packit 517ee8
		valid = el->valid && valid;
Packit 517ee8
	}
Packit 517ee8
	return valid;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
Packit 517ee8
/* Public */
Packit 517ee8
Packit 517ee8
yaml_path_t*
Packit 517ee8
yaml_path_create (void)
Packit 517ee8
{
Packit 517ee8
	yaml_path_t *ypath = malloc(sizeof(*ypath));
Packit 517ee8
Packit 517ee8
	assert(ypath != NULL);
Packit 517ee8
	memset (ypath, 0, sizeof(*ypath));
Packit 517ee8
	TAILQ_INIT(&ypath->sections_list);
Packit 517ee8
Packit 517ee8
	return ypath;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
int
Packit 517ee8
yaml_path_parse (yaml_path_t *path, char *s_path)
Packit 517ee8
{
Packit 517ee8
	if (path == NULL)
Packit 517ee8
		return -1;
Packit 517ee8
Packit 517ee8
	yaml_path_sections_remove(path);
Packit 517ee8
	memset(&path->error, 0, sizeof(path->error));
Packit 517ee8
Packit 517ee8
	_parse(path, s_path);
Packit 517ee8
Packit 517ee8
	if (path->sections_count == 0)
Packit 517ee8
		return -2;
Packit 517ee8
Packit 517ee8
	return 0;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
void
Packit 517ee8
yaml_path_destroy (yaml_path_t *path)
Packit 517ee8
{
Packit 517ee8
	if (path == NULL)
Packit 517ee8
		return;
Packit 517ee8
	yaml_path_sections_remove(path);
Packit 517ee8
	free(path);
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
/* API */
Packit 517ee8
Packit 517ee8
const yaml_path_error_t*
Packit 517ee8
yaml_path_error_get (yaml_path_t *path)
Packit 517ee8
{
Packit 517ee8
	if (path == NULL)
Packit 517ee8
		return NULL;
Packit 517ee8
	return &path->error;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
size_t
Packit 517ee8
yaml_path_snprint (yaml_path_t *path, char *s, size_t max_len)
Packit 517ee8
{
Packit 517ee8
	if (s == NULL)
Packit 517ee8
		return -1;
Packit 517ee8
	if (path == NULL)
Packit 517ee8
		return 0;
Packit 517ee8
Packit 517ee8
	size_t len = 0;
Packit 517ee8
	yaml_path_section_t *el;
Packit 517ee8
	TAILQ_FOREACH(el, &path->sections_list, entries) {
Packit 517ee8
		len += yaml_path_section_snprint(el, s + (len < max_len ? len : max_len), max_len - (len < max_len ? len : max_len));
Packit 517ee8
	}
Packit 517ee8
	return len;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
int
Packit 517ee8
yaml_path_filter_event (yaml_path_t *path, yaml_parser_t *parser, yaml_event_t *event, yaml_path_filter_mode_t mode)
Packit 517ee8
{
Packit 517ee8
	int res = 0;
Packit 517ee8
	const char *anchor = NULL;
Packit 517ee8
Packit 517ee8
	if (path == NULL || parser == NULL || event == NULL)
Packit 517ee8
		goto exit;
Packit 517ee8
Packit 517ee8
	switch(event->type) {
Packit 517ee8
	case YAML_MAPPING_START_EVENT:
Packit 517ee8
		anchor = (const char *)event->data.mapping_start.anchor;
Packit 517ee8
		break;
Packit 517ee8
	case YAML_SEQUENCE_START_EVENT:
Packit 517ee8
		anchor = (const char *)event->data.sequence_start.anchor;
Packit 517ee8
		break;
Packit 517ee8
	case YAML_SCALAR_EVENT:
Packit 517ee8
		anchor = (const char *)event->data.scalar.anchor;
Packit 517ee8
		break;
Packit 517ee8
	default:
Packit 517ee8
		break;
Packit 517ee8
	}
Packit 517ee8
Packit 517ee8
	if (!path->start_level) {
Packit 517ee8
		switch (yaml_path_section_get_first(path)->type) {
Packit 517ee8
		case YAML_PATH_SECTION_ROOT:
Packit 517ee8
			if (event->type == YAML_DOCUMENT_START_EVENT) {
Packit 517ee8
				path->start_level = 1;
Packit 517ee8
				yaml_path_section_get_first(path)->valid = true;
Packit 517ee8
			}
Packit 517ee8
			break;
Packit 517ee8
		case YAML_PATH_SECTION_ANCHOR:
Packit 517ee8
			if (anchor != NULL) {
Packit 517ee8
				if (!strcmp(yaml_path_section_get_first(path)->data.anchor, anchor)) {
Packit 517ee8
					path->start_level = path->current_level;
Packit 517ee8
					if (yaml_path_section_get_current(path))
Packit 517ee8
						yaml_path_section_get_current(path)->node_type = YAML_SCALAR_NODE;
Packit 517ee8
				}
Packit 517ee8
			}
Packit 517ee8
			break;
Packit 517ee8
		default:
Packit 517ee8
			//TODO: This path is invalid
Packit 517ee8
			break;
Packit 517ee8
		}
Packit 517ee8
	} else {
Packit 517ee8
		//TODO: ?
Packit 517ee8
	}
Packit 517ee8
Packit 517ee8
	yaml_path_section_t *current_section = yaml_path_section_get_current(path);
Packit 517ee8
	if (!current_section) {
Packit 517ee8
	} else {
Packit 517ee8
		switch (event->type) {
Packit 517ee8
		case YAML_DOCUMENT_START_EVENT:
Packit 517ee8
		case YAML_MAPPING_START_EVENT:
Packit 517ee8
		case YAML_SEQUENCE_START_EVENT:
Packit 517ee8
		case YAML_ALIAS_EVENT:
Packit 517ee8
		case YAML_SCALAR_EVENT:
Packit 517ee8
			switch (current_section->node_type) {
Packit 517ee8
			case YAML_SCALAR_NODE:
Packit 517ee8
				current_section->valid = true;
Packit 517ee8
				break;
Packit 517ee8
			case YAML_MAPPING_NODE:
Packit 517ee8
				if (current_section->type == YAML_PATH_SECTION_KEY) {
Packit 517ee8
					if (current_section->counter % 2) {
Packit 517ee8
						current_section->valid = current_section->next_valid;
Packit 517ee8
						current_section->next_valid = false;
Packit 517ee8
					} else {
Packit 517ee8
						current_section->next_valid = !strcmp(current_section->data.key, (const char *)event->data.scalar.value);
Packit 517ee8
						current_section->valid = false;
Packit 517ee8
					}
Packit 517ee8
				} else {
Packit 517ee8
					current_section->valid = false;
Packit 517ee8
				}
Packit 517ee8
				break;
Packit 517ee8
			case YAML_SEQUENCE_NODE:
Packit 517ee8
				if (current_section->type == YAML_PATH_SECTION_INDEX) {
Packit 517ee8
					current_section->valid = current_section->data.index == current_section->counter;
Packit 517ee8
				} else if (current_section->type == YAML_PATH_SECTION_SLICE) {
Packit 517ee8
					current_section->valid = current_section->data.slice.start <= current_section->counter &&
Packit 517ee8
					                         current_section->data.slice.end > current_section->counter &&
Packit 517ee8
					                         (current_section->data.slice.start + current_section->counter) % current_section->data.slice.stride == 0;
Packit 517ee8
				} else {
Packit 517ee8
					current_section->valid = false;
Packit 517ee8
				}
Packit 517ee8
				break;
Packit 517ee8
			default:
Packit 517ee8
				break;
Packit 517ee8
			}
Packit 517ee8
			current_section->counter++;
Packit 517ee8
		default:
Packit 517ee8
			break;
Packit 517ee8
		}
Packit 517ee8
	}
Packit 517ee8
Packit 517ee8
	switch (event->type) {
Packit 517ee8
	case YAML_STREAM_START_EVENT:
Packit 517ee8
	case YAML_STREAM_END_EVENT:
Packit 517ee8
	case YAML_NO_EVENT:
Packit 517ee8
		res = 1;
Packit 517ee8
		break;
Packit 517ee8
	case YAML_DOCUMENT_START_EVENT:
Packit 517ee8
		if (path->start_level == 1)
Packit 517ee8
			path->current_level++;
Packit 517ee8
		res = 1;
Packit 517ee8
		break;
Packit 517ee8
	case YAML_DOCUMENT_END_EVENT:
Packit 517ee8
		if (path->start_level == 1)
Packit 517ee8
			path->current_level--;
Packit 517ee8
		res = 1;
Packit 517ee8
		break;
Packit 517ee8
	case YAML_MAPPING_START_EVENT:
Packit 517ee8
	case YAML_SEQUENCE_START_EVENT:
Packit 517ee8
		if (current_section) {
Packit 517ee8
			if (yaml_path_section_current_is_last(path))
Packit 517ee8
				res = yaml_path_is_valid(path);
Packit 517ee8
		} else {
Packit 517ee8
			if (path->current_level > path->start_level) {
Packit 517ee8
				if (mode == YAML_PATH_FILTER_RETURN_ALL)
Packit 517ee8
					res = yaml_path_is_valid(path);
Packit 517ee8
			}
Packit 517ee8
		}
Packit 517ee8
		path->current_level++;
Packit 517ee8
		current_section = yaml_path_section_get_current(path);
Packit 517ee8
		if (current_section && yaml_path_section_current_is_mandatory_sequence(path)) {
Packit 517ee8
			res = yaml_path_sections_prev_are_valid(path);
Packit 517ee8
		}
Packit 517ee8
		if (current_section) {
Packit 517ee8
			current_section->node_type = event->type == YAML_MAPPING_START_EVENT ? YAML_MAPPING_NODE : YAML_SEQUENCE_NODE;
Packit 517ee8
			current_section->counter = 0;
Packit 517ee8
		}
Packit 517ee8
		break;
Packit 517ee8
	case YAML_MAPPING_END_EVENT:
Packit 517ee8
	case YAML_SEQUENCE_END_EVENT:
Packit 517ee8
		if (current_section) {
Packit 517ee8
			if (yaml_path_section_current_is_mandatory_sequence(path))
Packit 517ee8
				res = yaml_path_sections_prev_are_valid(path);
Packit 517ee8
		}
Packit 517ee8
		path->current_level--;
Packit 517ee8
		current_section = yaml_path_section_get_current(path);
Packit 517ee8
		if (current_section) {
Packit 517ee8
			if (yaml_path_section_current_is_last(path))
Packit 517ee8
				res = yaml_path_is_valid(path);
Packit 517ee8
		} else {
Packit 517ee8
			if (path->current_level > path->start_level) {
Packit 517ee8
				if (mode == YAML_PATH_FILTER_RETURN_ALL)
Packit 517ee8
					res = yaml_path_is_valid(path);
Packit 517ee8
			}
Packit 517ee8
		}
Packit 517ee8
		break;
Packit 517ee8
	case YAML_ALIAS_EVENT:
Packit 517ee8
	case YAML_SCALAR_EVENT:
Packit 517ee8
		if (!current_section) {
Packit 517ee8
			if ((mode == YAML_PATH_FILTER_RETURN_ALL && path->current_level > path->start_level) || path->current_level == path->start_level)
Packit 517ee8
				res = yaml_path_is_valid(path);
Packit 517ee8
		} else {
Packit 517ee8
			res = yaml_path_is_valid(path) && yaml_path_section_current_is_last(path);
Packit 517ee8
		}
Packit 517ee8
		break;
Packit 517ee8
	default:
Packit 517ee8
		break;
Packit 517ee8
	}
Packit 517ee8
Packit 517ee8
exit:
Packit 517ee8
	return res;
Packit 517ee8
}