summaryrefslogtreecommitdiffstats
path: root/contrib/libs/libfyaml/src/lib/fy-composer.c
diff options
context:
space:
mode:
authorDaniil Cherednik <[email protected]>2023-05-05 11:09:01 +0300
committerDaniil Cherednik <[email protected]>2023-05-05 11:09:01 +0300
commitb5a989b16cafa8a3b3bc076f1097a0eda6f48c06 (patch)
tree4da744117a5aab37758921fa43b95a3068e5aec1 /contrib/libs/libfyaml/src/lib/fy-composer.c
parentfc1cffcfa7f0497a1f97b384a24bcbf23362f3be (diff)
Ydb stable 23-1-2623.1.26
x-stable-origin-commit: 22184a7e157553d447f17a2dffc4ea2d32dfd74d
Diffstat (limited to 'contrib/libs/libfyaml/src/lib/fy-composer.c')
-rw-r--r--contrib/libs/libfyaml/src/lib/fy-composer.c356
1 files changed, 356 insertions, 0 deletions
diff --git a/contrib/libs/libfyaml/src/lib/fy-composer.c b/contrib/libs/libfyaml/src/lib/fy-composer.c
new file mode 100644
index 00000000000..2202497d695
--- /dev/null
+++ b/contrib/libs/libfyaml/src/lib/fy-composer.c
@@ -0,0 +1,356 @@
+/*
+ * fy-composer.c - Composer support
+ *
+ * Copyright (c) 2021 Pantelis Antoniou <[email protected]>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include <libfyaml.h>
+
+#include "fy-parse.h"
+#include "fy-doc.h"
+
+#include "fy-utils.h"
+
+struct fy_composer *
+fy_composer_create(struct fy_composer_cfg *cfg)
+{
+ struct fy_composer *fyc;
+ struct fy_path *fypp;
+
+ /* verify configuration and mandatory ops */
+ if (!cfg || !cfg->ops ||
+ !cfg->ops->process_event)
+ return NULL;
+
+ fyc = malloc(sizeof(*fyc));
+ if (!fyc)
+ return NULL;
+ memset(fyc, 0, sizeof(*fyc));
+ fyc->cfg = *cfg;
+
+ fy_path_list_init(&fyc->paths);
+ fypp = fy_path_create();
+ if (!fypp)
+ goto err_no_path;
+ fy_path_list_add_tail(&fyc->paths, fypp);
+
+ return fyc;
+
+err_no_path:
+ free(fyc);
+ return NULL;
+}
+
+void fy_composer_destroy(struct fy_composer *fyc)
+{
+ struct fy_path *fypp;
+
+ if (!fyc)
+ return;
+
+ fy_diag_unref(fyc->cfg.diag);
+ while ((fypp = fy_path_list_pop(&fyc->paths)) != NULL)
+ fy_path_destroy(fypp);
+ free(fyc);
+}
+
+static enum fy_composer_return
+fy_composer_process_event_private(struct fy_composer *fyc, struct fy_event *fye, struct fy_path *fypp)
+{
+ const struct fy_composer_ops *ops;
+ struct fy_eventp *fyep;
+ struct fy_path_component *fypc, *fypc_last;
+ struct fy_path *fyppt;
+ struct fy_document *fyd;
+ bool is_collection, is_map, is_start, is_end;
+ int rc = 0;
+ enum fy_composer_return ret;
+ bool stop_req = false;
+
+ assert(fyc);
+ assert(fye);
+ assert(fypp);
+
+ fyep = fy_container_of(fye, struct fy_eventp, e);
+
+ ops = fyc->cfg.ops;
+ assert(ops);
+
+ rc = 0;
+
+ switch (fye->type) {
+ case FYET_MAPPING_START:
+ is_collection = true;
+ is_start = true;
+ is_end = false;
+ is_map = true;
+ break;
+
+ case FYET_MAPPING_END:
+ is_collection = true;
+ is_start = false;
+ is_end = true;
+ is_map = true;
+ break;
+
+ case FYET_SEQUENCE_START:
+ is_collection = true;
+ is_start = true;
+ is_end = false;
+ is_map = false;
+ break;
+
+ case FYET_SEQUENCE_END:
+ is_collection = true;
+ is_start = false;
+ is_end = true;
+ is_map = false;
+ break;
+
+ case FYET_SCALAR:
+ is_collection = false;
+ is_start = true;
+ is_end = true;
+ is_map = false;
+ break;
+
+ case FYET_ALIAS:
+ is_collection = false;
+ is_start = true;
+ is_end = true;
+ is_map = false;
+ break;
+
+ case FYET_STREAM_START:
+ case FYET_STREAM_END:
+ case FYET_DOCUMENT_START:
+ case FYET_DOCUMENT_END:
+ return ops->process_event(fyc, fypp, fye);
+
+ default:
+ return FYCR_OK_CONTINUE;
+ }
+
+ fypc_last = fy_path_component_list_tail(&fypp->components);
+
+ if (fy_path_component_is_mapping(fypc_last) && fypc_last->map.accumulating_complex_key) {
+
+ /* get the next one */
+ fyppt = fy_path_next(&fyc->paths, fypp);
+ assert(fyppt);
+ assert(fyppt != fypp);
+ assert(fyppt->parent == fypp);
+
+ /* and pass along */
+ ret = fy_composer_process_event_private(fyc, fye, fyppt);
+ if (!fy_composer_return_is_ok(ret)) {
+ /* XXX TODO handle skip */
+ return ret;
+ }
+ if (!stop_req)
+ stop_req = ret == FYCR_OK_STOP;
+
+ rc = fy_document_builder_process_event(fypp->fydb, fyep);
+ if (rc == 0)
+ return FYCR_OK_CONTINUE;
+ fyc_error_check(fyc, rc > 0, err_out,
+ "fy_document_builder_process_event() failed\n");
+
+ /* get the document */
+ fyd = fy_document_builder_take_document(fypp->fydb);
+ fyc_error_check(fyc, fyd, err_out,
+ "fy_document_builder_take_document() failed\n");
+
+ fypc_last->map.is_complex_key = true;
+ fypc_last->map.accumulating_complex_key = false;
+ fypc_last->map.complex_key = fyd;
+ fypc_last->map.has_key = true;
+ fypc_last->map.await_key = false;
+ fypc_last->map.complex_key_complete = true;
+ fypc_last->map.root = false;
+
+ fyppt = fy_path_list_pop_tail(&fyc->paths);
+ assert(fyppt);
+
+ fy_path_destroy(fyppt);
+
+ fyc_error_check(fyc, rc >= 0, err_out,
+ "fy_path_component_build_text() failed\n");
+
+ return !stop_req ? FYCR_OK_CONTINUE : FYCR_OK_STOP;
+ }
+
+ /* start of something on a mapping */
+ if (is_start && fy_path_component_is_mapping(fypc_last) && fypc_last->map.await_key && is_collection) {
+
+ /* the configuration must support a document builder for complex keys */
+ FYC_TOKEN_ERROR_CHECK(fyc, fy_event_get_token(fye), FYEM_DOC,
+ ops->create_document_builder, err_out,
+ "composer configuration does not support complex keys");
+
+ /* call out for creating the document builder */
+ fypp->fydb = ops->create_document_builder(fyc);
+ fyc_error_check(fyc, fypp->fydb, err_out,
+ "ops->create_document_builder() failed\n");
+
+ /* and pass the current event; must return 0 since we know it's a collection start */
+ rc = fy_document_builder_process_event(fypp->fydb, fyep);
+ fyc_error_check(fyc, !rc, err_out,
+ "fy_document_builder_process_event() failed\n");
+
+ fypc_last->map.is_complex_key = true;
+ fypc_last->map.accumulating_complex_key = true;
+ fypc_last->map.complex_key = NULL;
+ fypc_last->map.complex_key_complete = false;
+
+ /* create new path */
+ fyppt = fy_path_create();
+ fyc_error_check(fyc, fyppt, err_out,
+ "fy_path_create() failed\n");
+
+ /* append it to the end */
+ fyppt->parent = fypp;
+ fy_path_list_add_tail(&fyc->paths, fyppt);
+
+ /* and pass along */
+ ret = fy_composer_process_event_private(fyc, fye, fyppt);
+ if (!fy_composer_return_is_ok(ret)) {
+ /* XXX TODO handle skip */
+ return ret;
+ }
+ if (!stop_req)
+ stop_req = ret == FYCR_OK_STOP;
+
+ return !stop_req ? FYCR_OK_CONTINUE : FYCR_OK_STOP;
+ }
+
+ if (is_start && fy_path_component_is_sequence(fypc_last)) { /* start in a sequence */
+
+ if (fypc_last->seq.idx < 0)
+ fypc_last->seq.idx = 0;
+ else
+ fypc_last->seq.idx++;
+ }
+
+ if (is_collection && is_start) {
+
+ /* collection start */
+ if (is_map) {
+ fypc = fy_path_component_create_mapping(fypp);
+ fyc_error_check(fyc, fypc, err_out,
+ "fy_path_component_create_mapping() failed\n");
+ } else {
+ fypc = fy_path_component_create_sequence(fypp);
+ fyc_error_check(fyc, fypc, err_out,
+ "fy_path_component_create_sequence() failed\n");
+ }
+
+ /* append to the tail */
+ fy_path_component_list_add_tail(&fypp->components, fypc);
+
+ } else if (is_collection && is_end) {
+
+ /* collection end */
+ assert(fypc_last);
+ fy_path_component_clear_state(fypc_last);
+
+ } else if (!is_collection && fy_path_component_is_mapping(fypc_last) && fypc_last->map.await_key) {
+
+ fypc_last->map.is_complex_key = false;
+ fypc_last->map.scalar.tag = fy_token_ref(fy_event_get_tag_token(fye));
+ fypc_last->map.scalar.key = fy_token_ref(fy_event_get_token(fye));
+ fypc_last->map.has_key = true;
+ fypc_last->map.root = false;
+
+ }
+
+ /* process the event */
+ ret = ops->process_event(fyc, fypp, fye);
+ if (!fy_composer_return_is_ok(ret)) {
+ /* XXX TODO handle skip */
+ return ret;
+ }
+ if (!stop_req)
+ stop_req = ret == FYCR_OK_STOP;
+
+ if (is_collection && is_end) {
+ /* for the end of a collection, pop the last component */
+ fypc = fy_path_component_list_pop_tail(&fypp->components);
+ assert(fypc);
+
+ assert(fypc == fypc_last);
+
+ fy_path_component_recycle(fypp, fypc);
+
+ /* and get the new last */
+ fypc_last = fy_path_component_list_tail(&fypp->components);
+ }
+
+ /* at the end of something */
+ if (is_end && fy_path_component_is_mapping(fypc_last)) {
+ if (!fypc_last->map.await_key) {
+ fy_path_component_clear_state(fypc_last);
+ fypc_last->map.await_key = true;
+ } else
+ fypc_last->map.await_key = false;
+ }
+
+ return !stop_req ? FYCR_OK_CONTINUE : FYCR_OK_STOP;
+
+err_out:
+ return FYCR_ERROR;
+}
+
+enum fy_composer_return
+fy_composer_process_event(struct fy_composer *fyc, struct fy_event *fye)
+{
+ struct fy_path *fypp;
+ int rc;
+
+ if (!fyc || !fye)
+ return -1;
+
+ /* start at the head */
+ fypp = fy_path_list_head(&fyc->paths);
+
+ /* no top? something's very out of order */
+ if (!fypp)
+ return -1;
+
+ rc = fy_composer_process_event_private(fyc, fye, fypp);
+
+ return rc;
+}
+
+struct fy_composer_cfg *fy_composer_get_cfg(struct fy_composer *fyc)
+{
+ if (!fyc)
+ return NULL;
+ return &fyc->cfg;
+}
+
+void *fy_composer_get_cfg_userdata(struct fy_composer *fyc)
+{
+ if (!fyc)
+ return NULL;
+ return fyc->cfg.userdata;
+}
+
+struct fy_diag *fy_composer_get_diag(struct fy_composer *fyc)
+{
+ if (!fyc)
+ return NULL;
+ return fyc->cfg.diag;
+}