Patchwork [U-Boot,4/5] libfdt: Add fdt_next_subnode() to permit easy subnode iteration

login
register
mail settings
Submitter Jerry Van Baren
Date May 6, 2013, 11:31 p.m.
Message ID <1367883119-25596-5-git-send-email-gvb.uboot@gmail.com>
Download mbox | patch
Permalink /patch/241832/
State Superseded
Delegated to: Jerry Van Baren
Headers show

Comments

Jerry Van Baren - May 6, 2013, 11:31 p.m.
From: Simon Glass <sjg@chromium.org>

Iterating through subnodes with libfdt is a little painful to write as we
need something like this:

for (depth = 0, count = 0,
	offset = fdt_next_node(fdt, parent_offset, &depth);
     (offset >= 0) && (depth > 0);
     offset = fdt_next_node(fdt, offset, &depth)) {
	if (depth == 1) {
		/* code body */
	}
}

Using fdt_next_subnode() we can instead write this, which is shorter and
easier to get right:

for (offset = fdt_first_subnode(fdt, parent_offset);
     offset >= 0;
     offset = fdt_next_subnode(fdt, offset)) {
	/* code body */
}

Also, it doesn't require two levels of indentation for the loop body.

Signed-off-by: Simon Glass <sjg@chromium.org>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
---
 include/libfdt.h |   22 ++++++++++++++++++++++
 lib/libfdt/fdt.c |   28 ++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)
Simon Glass - May 7, 2013, 4:31 p.m.
On Mon, May 6, 2013 at 5:31 PM,  <gvb.uboot@gmail.com> wrote:
> From: Simon Glass <sjg@chromium.org>
>
> Iterating through subnodes with libfdt is a little painful to write as we
> need something like this:
>
> for (depth = 0, count = 0,
>         offset = fdt_next_node(fdt, parent_offset, &depth);
>      (offset >= 0) && (depth > 0);
>      offset = fdt_next_node(fdt, offset, &depth)) {
>         if (depth == 1) {
>                 /* code body */
>         }
> }
>
> Using fdt_next_subnode() we can instead write this, which is shorter and
> easier to get right:
>
> for (offset = fdt_first_subnode(fdt, parent_offset);
>      offset >= 0;
>      offset = fdt_next_subnode(fdt, offset)) {
>         /* code body */
> }
>
> Also, it doesn't require two levels of indentation for the loop body.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> Acked-by: David Gibson <david@gibson.dropbear.id.au>

Acked-by: Simon Glass <sjg@chromium.org>

Patch

diff --git a/include/libfdt.h b/include/libfdt.h
index 7403d5a..c5ec2ac 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -136,6 +136,28 @@  uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
 
 int fdt_next_node(const void *fdt, int offset, int *depth);
 
+/**
+ * fdt_first_subnode() - get offset of first direct subnode
+ *
+ * @fdt:	FDT blob
+ * @offset:	Offset of node to check
+ * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
+ */
+int fdt_first_subnode(const void *fdt, int offset);
+
+/**
+ * fdt_next_subnode() - get offset of next direct subnode
+ *
+ * After first calling fdt_first_subnode(), call this function repeatedly to
+ * get direct subnodes of a parent node.
+ *
+ * @fdt:	FDT blob
+ * @offset:	Offset of previous subnode
+ * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
+ * subnodes
+ */
+int fdt_next_subnode(const void *fdt, int offset);
+
 /**********************************************************************/
 /* General functions                                                  */
 /**********************************************************************/
diff --git a/lib/libfdt/fdt.c b/lib/libfdt/fdt.c
index 387e354..154e9a4 100644
--- a/lib/libfdt/fdt.c
+++ b/lib/libfdt/fdt.c
@@ -202,6 +202,34 @@  int fdt_next_node(const void *fdt, int offset, int *depth)
 	return offset;
 }
 
+int fdt_first_subnode(const void *fdt, int offset)
+{
+	int depth = 0;
+
+	offset = fdt_next_node(fdt, offset, &depth);
+	if (offset < 0 || depth != 1)
+		return -FDT_ERR_NOTFOUND;
+
+	return offset;
+}
+
+int fdt_next_subnode(const void *fdt, int offset)
+{
+	int depth = 1;
+
+	/*
+	 * With respect to the parent, the depth of the next subnode will be
+	 * the same as the last.
+	 */
+	do {
+		offset = fdt_next_node(fdt, offset, &depth);
+		if (offset < 0 || depth < 1)
+			return -FDT_ERR_NOTFOUND;
+	} while (depth > 1);
+
+	return offset;
+}
+
 const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
 {
 	int len = strlen(s) + 1;