[libfdt] RFC: Node iterators
David Gibson
david at gibson.dropbear.id.au
Wed Jan 16 17:20:22 EST 2008
Here's my counter-attempt at node iterators for libfdt. It's based on
an internal function very similar to Scott's fdt_next_node(), but the
exported interfaces are altered to be (IMO) safer and simpler.
So far, it only handles iterating across immediate children of a node,
not traversing an entire subtree. I'm still working on extending the
internals to cover that case. No property iteration as yet, either.
Index: dtc/libfdt/fdt_ro.c
===================================================================
--- dtc.orig/libfdt/fdt_ro.c 2008-01-16 15:06:49.000000000 +1100
+++ dtc/libfdt/fdt_ro.c 2008-01-16 16:27:55.000000000 +1100
@@ -65,7 +65,7 @@
static int nodename_eq(const void *fdt, int offset,
const char *s, int len)
{
- const char *p = fdt_offset_ptr(fdt, offset, len+1);
+ const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
if (! p)
/* short match */
@@ -104,50 +104,16 @@ int fdt_num_mem_rsv(const void *fdt)
return i;
}
-int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
+int fdt_subnode_offset_namelen(const void *fdt, int offset,
const char *name, int namelen)
{
- int level = 0;
- uint32_t tag;
- int offset, nextoffset;
-
CHECK_HEADER(fdt);
- tag = fdt_next_tag(fdt, parentoffset, &nextoffset);
- if (tag != FDT_BEGIN_NODE)
- return -FDT_ERR_BADOFFSET;
-
- do {
- offset = nextoffset;
- tag = fdt_next_tag(fdt, offset, &nextoffset);
-
- switch (tag) {
- case FDT_END:
- return -FDT_ERR_TRUNCATED;
-
- case FDT_BEGIN_NODE:
- level++;
- if (level != 1)
- continue;
- if (nodename_eq(fdt, offset+FDT_TAGSIZE, name, namelen))
- /* Found it! */
- return offset;
- break;
-
- case FDT_END_NODE:
- level--;
- break;
-
- case FDT_PROP:
- case FDT_NOP:
- break;
-
- default:
- return -FDT_ERR_BADSTRUCTURE;
- }
- } while (level >= 0);
+ for_each_subnode(fdt, offset)
+ if (nodename_eq(fdt, offset, name, namelen))
+ return offset;
- return -FDT_ERR_NOTFOUND;
+ return offset;
}
int fdt_subnode_offset(const void *fdt, int parentoffset,
Index: dtc/libfdt/fdt.c
===================================================================
--- dtc.orig/libfdt/fdt.c 2008-01-16 16:26:48.000000000 +1100
+++ dtc/libfdt/fdt.c 2008-01-16 17:03:09.000000000 +1100
@@ -129,6 +129,58 @@ uint32_t fdt_next_tag(const void *fdt, i
return tag;
}
+static int _fdt_next_node(const void *fdt, int offset, int *depth)
+{
+ uint32_t tag;
+ int nextoffset;
+
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+ if (tag != FDT_BEGIN_NODE)
+ return -FDT_ERR_BADOFFSET;
+
+ do {
+ offset = nextoffset;
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+ switch (tag) {
+ case FDT_PROP:
+ case FDT_NOP:
+ break;
+
+ case FDT_BEGIN_NODE:
+ (*depth)++;
+ if (*depth == 1)
+ return offset;
+ break;
+
+ case FDT_END_NODE:
+ (*depth)--;
+ break;
+
+ case FDT_END:
+ return -FDT_ERR_TRUNCATED;
+
+ default:
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+ } while (*depth >= 0);
+
+ return -FDT_ERR_NOTFOUND;
+}
+
+int _fdt_first_subnode(const void *fdt, int offset)
+{
+ int depth = 0;
+
+ return _fdt_next_node(fdt, offset, &depth);
+}
+
+int _fdt_next_subnode(const void *fdt, int offset)
+{
+ int depth = 1;
+ return _fdt_next_node(fdt, offset, &depth);
+}
+
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
{
int len = strlen(s) + 1;
Index: dtc/libfdt/libfdt.h
===================================================================
--- dtc.orig/libfdt/libfdt.h 2008-01-16 16:27:09.000000000 +1100
+++ dtc/libfdt/libfdt.h 2008-01-16 17:06:31.000000000 +1100
@@ -131,6 +131,18 @@ static inline void *fdt_offset_ptr_w(voi
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
/**********************************************************************/
+/* Traversal functions */
+/**********************************************************************/
+
+int _fdt_first_subnode(const void *fdt, int offset);
+int _fdt_next_subnode(const void *fdt, int offset);
+
+#define for_each_subnode(fdt, offset) \
+ for ((offset) = _fdt_first_subnode((fdt), (offset)); \
+ (offset) >= 0; \
+ (offset) = _fdt_next_subnode((fdt), (offset)))
+
+/**********************************************************************/
/* General functions */
/**********************************************************************/
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
More information about the Linuxppc-dev
mailing list