aboutsummaryrefslogtreecommitdiff
path: root/src/yaml.h
diff options
context:
space:
mode:
authorDavid Timber <dxdt@dev.snart.me>2022-10-18 14:50:48 +0800
committerDavid Timber <dxdt@dev.snart.me>2022-10-18 14:50:48 +0800
commit8b47484919d61d389dfdefb07fe1b168021696e7 (patch)
tree7feb68d11dd73e3b98a43628572d9b70442dd085 /src/yaml.h
parent44d5b5b1bada4ef81a8b82612e8e248729c71e5d (diff)
Add yaml.h, hostinfod bug fix, compilation setting
- Add yaml helper functions - Add yaml test tool proone-yamlls - Add yaml test doc - Refactor hostinfod with yaml.h - Fix bug in hostinfod where specifying verbosity results in config error - Add C flag '-Werror=implicit-function-declaration' - Update doxygen template
Diffstat (limited to 'src/yaml.h')
-rw-r--r--src/yaml.h251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/yaml.h b/src/yaml.h
new file mode 100644
index 0000000..eafc964
--- /dev/null
+++ b/src/yaml.h
@@ -0,0 +1,251 @@
+/** \file
+ * \brief The YAML helper. Only listen to terminating scalar events: the helper
+ * removes the need to listen to mapping start and sequence start events in
+ * between. The mapping and sequence start events are reformed as
+ * \c prne_yaml_path_t which can be converted to a file-system-path-like string
+ * using \c prne_yaml_path_tostr() The string can be matched against regexp or
+ * simple string mapping to extract data from the document.
+ */
+/*
+* Copyright (c) 2019-2021 David Timber <mieabby@gmail.com>
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all
+* copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+#pragma once
+#include <yaml.h>
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+#include "util_ct.h"
+#include "llist.h"
+
+
+typedef enum {
+ PRNE_YAML_PR_NALIAS = -3, // Alias encountered
+ PRNE_YAML_PR_ERRNO, // errno set
+ PRNE_YAML_PR_APIERR, // libyaml error
+ PRNE_YAML_PR_CBHALT, // cb func returned false
+ PRNE_YAML_PR_END // no more event
+} prne_yaml_parse_ret_t;
+prne_static_assert(PRNE_YAML_PR_CBHALT == 0, "PRNE_YAML_PR_CBHALT == 0");
+
+typedef enum {
+ PRNE_YAML_ENT_NONE,
+ PRNE_YAML_ENT_MAP, // entry representing a mapping start
+ PRNE_YAML_ENT_SEQ // entry representing a sequence start
+} prne_yaml_ent_type_t;
+
+/**
+ * \brief Path entry object. One path entry corresponds to one mapping or
+ * sequence start event.
+ */
+typedef struct {
+ // Entry type: mapping or sequence
+ prne_yaml_ent_type_t type;
+ union {
+ // Data for mapping entry
+ struct {
+ char *name; // The first scalar value of the mapping
+ bool own; // True if the object has the ownership of \c name
+ } map;
+ // Data for sequence entry
+ struct {
+ size_t idx; // Index from the first occurrence in sequence
+ } seq;
+ };
+} prne_yaml_path_entry_t;
+
+/**
+ * \brief Path object
+ */
+typedef struct {
+ // The number of entries
+ size_t depth;
+ // The entries with the elements in the order of events occurrence.
+ prne_yaml_path_entry_t *entries;
+ // True if the object is responsible for freeing the path entries
+ bool own;
+} prne_yaml_path_t;
+
+/**
+ * \brief Callback function set object
+ */
+typedef struct {
+ // YAML_DOCUMENT_START_EVENT
+ bool(*doc_start)(void *ctx, const yaml_event_t *event);
+ // YAML_DOCUMENT_END_EVENT
+ bool(*doc_end)(void *ctx, const yaml_event_t *event);
+ // Terminating YAML_SCALAR_EVENT
+ bool(*scalar)(
+ void *ctx,
+ const char *value,
+ const prne_yaml_path_t *path);
+ /**
+ * \brief Anchor event
+ * \details This is a special event that is emitted prior to
+ * processing the event from libyaml. It can be used to support anchors and
+ * aliases in the document. The events that can have anchor are:
+ * - scalar
+ * - sequence start
+ * - mapping start
+ * The alias events can be processed in the separate callback function.
+ *
+ * Handling of anchors and aliases is expensive and impractical. The helper
+ * won't accept aliases unless requested.
+ *
+ * \see \c prne_yaml_parse_opt_t
+ * \see \c PRNE_YAML_PR_NALIAS
+ */
+ bool(*anchor)(
+ void *ctx,
+ const char *anchor,
+ const prne_yaml_path_t *path);
+ // YAML_ALIAS_EVENT
+ bool(*alias)(
+ void *ctx,
+ const char *anchor,
+ const prne_yaml_path_t *path);
+} prne_yaml_cbset_t;
+
+/**
+ * \brief Parsing Option Object
+ */
+typedef struct {
+ void *uctx; // User context for callback functions
+ prne_yaml_cbset_t cb; // Callback function set object
+ /* Accept anchors and anliases. Not allowed by default - the parser will
+ * produce an error if the document contains an anchor or an alias.
+ */
+ bool accept_alias;
+} prne_yaml_parse_opt_t;
+
+typedef struct {
+ // A pointer to a parsing Option Object instnace
+ const prne_yaml_parse_opt_t *opt;
+ // Internal path stack
+ prne_llist_t path_st;
+ // Internal path object
+ prne_yaml_path_t path;
+} prne_yaml_ctx_t;
+
+
+/**
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
+ */
+void prne_yaml_init_parse_opt (prne_yaml_parse_opt_t *p);
+/**
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
+ */
+void prne_yaml_free_parse_opt (prne_yaml_parse_opt_t *p);
+
+/**
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
+ */
+void prne_yaml_init_ctx (prne_yaml_ctx_t *ctx);
+/**
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
+ */
+void prne_yaml_free_ctx (prne_yaml_ctx_t *ctx);
+prne_yaml_parse_ret_t prne_yaml_do_parse (
+ yaml_parser_t *parser,
+ prne_yaml_ctx_t *ctx,
+ const prne_yaml_parse_opt_t *opt);
+
+const char *prne_yaml_pr_tostr (const prne_yaml_parse_ret_t x);
+
+/**
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
+ */
+void prne_yaml_init_path_entry (prne_yaml_path_entry_t *p);
+/**
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
+ */
+void prne_yaml_free_path_entry (prne_yaml_path_entry_t *p);
+
+/**
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
+ */
+void prne_yaml_init_path (prne_yaml_path_t *p);
+/**
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
+ */
+void prne_yaml_free_path (prne_yaml_path_t *p);
+/**
+ * \brief Allocate variable-length members of the Path Object
+ * \param p The pointer to the object
+ * \param depth The number of elements required
+ * \return true if allocation was successful
+ * \return false on failure and \c errno set to \c ENOMEM
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
+ */
+bool prne_yaml_alloc_path (prne_yaml_path_t *p, const size_t depth);
+/**
+ * \brief Deep copy operator
+ *
+ * \param src The source object
+ * \param dst The destination object. The original contents are be freed
+ * \return true on successful operation
+ * \return false on failure and \c errno set to \c ENOMEM
+ */
+bool prne_yaml_copy_path (const prne_yaml_path_t *src, prne_yaml_path_t *dst);
+/**
+ * \brief Swap operator
+ */
+void prne_yaml_swap_path (prne_yaml_path_t *a, prne_yaml_path_t *b);
+/**
+ * \brief Move opeator. Moves the contents of \p a into \p b The original
+ * contents of \p b are freed
+ */
+void prne_yaml_move_path (prne_yaml_path_t *a, prne_yaml_path_t *b);
+/**
+ * \brief The comparison operator
+ * \returns Negative value if \p a is less than \p b
+ * \returns Positive value if \p a is greater than \p b
+ * \retval 0 if \p a and \p b are identical
+ */
+int prne_yaml_cmp_path (const prne_yaml_path_t *a, const prne_yaml_path_t *b);
+/**
+ * \brief Fabricate string representation of the Path Object
+ *
+ * \param path The object
+ * \param path_sep The path separator. Conventionally "/" or "."
+ * \param ovr Set true to allow the path separator in path names
+ * \param old The old pointer to the string for \c prne_rebuild_str()
+ * \returns A pointer to the fabricated string
+ * \retval NULL and \c errno set to \c ENOMEM on memory allocation error
+ * \retval NULL and \c errno set to \c EINVAL if \p path_sep is NULL or a
+ * pointer to an empty string
+ * \retval NULL and \c errno set to \c EILSEQ if \p ovr is set and the path
+ * separator was found in one of the path names
+ */
+char *prne_yaml_path_tostr (
+ const prne_yaml_path_t *path,
+ const char *path_sep,
+ const bool ovr,
+ char *old);