]> git.mdlowis.com Git - proto/labwc.git/commitdiff
common/xml: add helpers to parse rc.xml
authortokyo4j <hrak1529@gmail.com>
Fri, 11 Apr 2025 11:25:12 +0000 (20:25 +0900)
committerJohan Malm <johanmalm@users.noreply.github.com>
Wed, 30 Jul 2025 19:36:27 +0000 (20:36 +0100)
include/common/xml.h
scripts/checkpatch.pl
src/common/xml.c
t/meson.build

index 7bc8eb26f83cbb05a41076e2d6487b46016d198f..3cfa5539f3d46852185a44fbf5a32eb59e8013f1 100644 (file)
@@ -3,6 +3,7 @@
 #define LABWC_XML_H
 
 #include <libxml/tree.h>
+#include <stdbool.h>
 
 /*
  * Converts dotted attributes into nested nodes.
  */
 void lab_xml_expand_dotted_attributes(xmlNode *root);
 
+/* Returns true if the node only contains a string or is empty */
+bool lab_xml_node_is_leaf(xmlNode *node);
+
+bool lab_xml_get_node(xmlNode *node, const char *key, xmlNode **dst_node);
+bool lab_xml_get_string(xmlNode *node, const char *key, char *s, size_t len);
+bool lab_xml_get_int(xmlNode *node, const char *key, int *i);
+bool lab_xml_get_bool(xmlNode *node, const char *key, bool *b);
+
+static inline xmlNode *
+lab_xml_get_next_child(xmlNode *child)
+{
+       if (!child) {
+               return NULL;
+       }
+       do {
+               child = child->next;
+       } while (child && child->type != XML_ELEMENT_NODE);
+
+       return child;
+}
+
+static inline void
+lab_xml_get_key_and_content(xmlNode *node, char **name, char **content)
+{
+       if (node) {
+               *name = (char *)node->name;
+               *content = (char *)xmlNodeGetContent(node);
+       }
+}
+
+#define LAB_XML_FOR_EACH(parent, child, key, content) \
+       for ((child) = (parent)->children, \
+               lab_xml_get_key_and_content((child), &(key), &(content)); \
+               (child); \
+               xmlFree((xmlChar *)(content)), \
+               (child) = lab_xml_get_next_child(child), \
+               lab_xml_get_key_and_content((child), &(key), &(content)))
+
 #endif /* LABWC_XML_H */
index 6f835f22f9691f0df243ca4e9267d3a3d447284c..f9e9d1d9ab04d47f7ba281888fa146016617e25b 100755 (executable)
@@ -5532,6 +5532,7 @@ sub process {
                        if ($starts_with_if_while_etc && !length($s)
                                        && $filename ne "include/view.h"
                                        && $filename ne "include/common/array.h"
+                                       && $filename ne "include/common/xml.h"
                                        && $filename ne "include/ssd-internal.h") {
                                CHK("BRACES", "[labwc-custom] open brace { expected after if/while/for/switch - even with single statement blocks");
                        }
index 08ec18b63787c044dfc97aece1c0f794c08434bb..df8c26e4a34d1fa1ab20f89aae472f8736174a51 100644 (file)
@@ -4,6 +4,7 @@
 #include <stdbool.h>
 #include <strings.h>
 #include "common/xml.h"
+#include "common/parse-bool.h"
 
 /*
  * Converts an attribute A.B.C="X" into <C><B><A>X</A></B></C>
@@ -129,3 +130,69 @@ lab_xml_expand_dotted_attributes(xmlNode *parent)
                lab_xml_expand_dotted_attributes(node);
        }
 }
+
+bool
+lab_xml_node_is_leaf(xmlNode *node)
+{
+       if (node->type != XML_ELEMENT_NODE) {
+               return false;
+       }
+       for (xmlNode *child = node->children; child; child = child->next) {
+               if (child->type != XML_TEXT_NODE) {
+                       return false;
+               }
+       }
+       return true;
+}
+
+static bool
+get_node(xmlNode *node, const char *key, xmlNode **dst_node, bool leaf_only)
+{
+       for (xmlNode *child = node->last; child; child = child->prev) {
+               if (child->type != XML_ELEMENT_NODE) {
+                       continue;
+               }
+               if (leaf_only && !lab_xml_node_is_leaf(child)) {
+                       continue;
+               }
+               if (!strcasecmp((char *)child->name, key)) {
+                       *dst_node = child;
+                       return true;
+               }
+       }
+       return false;
+}
+
+bool
+lab_xml_get_node(xmlNode *node, const char *key, xmlNode **dst_node)
+{
+       return get_node(node, key, dst_node, /* leaf_only */ false);
+}
+
+bool
+lab_xml_get_string(xmlNode *node, const char *key, char *s, size_t len)
+{
+       xmlNode *child;
+       if (get_node(node, key, &child, /* leaf_only */ true)) {
+               xmlChar *content = xmlNodeGetContent(child);
+               g_strlcpy(s, (char *)content, len);
+               xmlFree(content);
+               return true;
+       }
+       return false;
+}
+
+bool
+lab_xml_get_bool(xmlNode *node, const char *key, bool *b)
+{
+       xmlNode *child;
+       if (get_node(node, key, &child, /* leaf_only */ true)) {
+               char *s = (char *)xmlNodeGetContent(child);
+               int ret = parse_bool(s, -1);
+               if (ret >= 0) {
+                       *b = ret;
+                       return true;
+               }
+       }
+       return false;
+}
index 66534a2c56020219a97e7d936f5160041ea2c2d1..6aafc1e976026be2d59cab58f868537feac1fff1 100644 (file)
@@ -5,12 +5,14 @@ test_lib = static_library(
     '../src/common/mem.c',
     '../src/common/string-helpers.c',
     '../src/common/xml.c',
+    '../src/common/parse-bool.c',
   ),
   include_directories: [labwc_inc],
   dependencies: [
                dep_cmocka,
                glib,
                xml2,
+               wlroots,
        ],
 )